Deployment Topologies
Run one middleware per POS counter, or host a single central instance that serves many TCP/IP terminals across lanes and branches.
Standard: One Middleware per POS counter
The default deployment is one-to-one: the middleware runs on the same PC as the POS application, talking to one terminal (COM or TCP/IP) physically near that PC. This is what the installer sets up out of the box and what the rest of this guide assumes unless noted otherwise.
Centralized: One Middleware, many TCP/IP terminals
TCP/IP terminals only need to be network-reachable — they don't need to be physically near, or even on the same site as, the machine running the middleware. This means a single middleware instance, installed on one central server, can act as the one communications point for many Nami terminals at once — across multiple checkout lanes, or even multiple branch locations — as long as each terminal's IP address is reachable from that server (same LAN, a site-to-site VPN, or routed WAN).
POS Lane 1 ──┐ ┌──► Terminal A (ip:portA)
POS Lane 2 ──┼──► Central Nami Middleware ──┼──► Terminal B (ip:portB)
POS Lane 3 ──┘ (one instance) └──► Terminal C (ip:portC)
Each transaction request still targets exactly one terminal, specified per-request via tcpipcomData.ip / tcpipcomData.port — there's no fan-out or broadcast to multiple terminals in a single call. What changes is just where the middleware is hosted relative to the terminals and POS applications: instead of one middleware per lane, one central instance serves requests for whichever terminal each request names. The existing TCP/IP connection persistence and Terminal ID registration keymap already support multiple parallel terminals keyed by ip:port (see Connection persistence & auto-reconnect), so this topology doesn't require any extra configuration beyond pointing every POS application's requests at the central server's base URL instead of localhost.
COM (USB) terminals cannot use this topology
A COM terminal must be physically cabled to whichever machine runs the middleware instance talking to it — there's no equivalent of a "remote COM port" here. Only TCP/IP terminals can be centrally hosted.
Known limitation: cancelling one terminal's transaction
POST /cancelTransactioncancels only the single most-recently-started transaction across the whole middleware instance — it does not currently accept a terminal identifier, so it cannot target one specific terminal's transaction when several are in flight at once. In a centralized multi-terminal deployment, avoid relying on/cancelTransactionwhen more than one transaction may be active simultaneously. This is an area planned for future work.
Network & security considerations
The API has no built-in authentication, and cors.urls defaults to * (allow all origins). This is a reasonable default for a single local machine behind its own firewall, but a centrally hosted instance is reachable by design from multiple lanes/locations, so it warrants more care:
- Restrict network access to the middleware's port (default
9099) at the network level — a site-to-site VPN, a firewall allow-list scoped to your branch/lane networks, or a reverse proxy in front of it that adds authentication. The middleware itself does not authenticate requests. - Narrow
cors.urlsto the specific origin(s) of any browser-based POS application calling the middleware directly, rather than leaving the default*wide open, since the attack surface is larger once the instance is reachable beyond one trusted local machine. - Consider HTTPS (the dashboard's "Switch to HTTPS" toggle) since traffic may now cross network segments rather than staying on
localhost. - Re-check
ecr.transaction.timeout.seconds(default30) if terminals are geographically distributed — WAN latency may warrant a longer timeout than a same-LAN deployment needs.
