Rorix Technologies Logo
WMS Architecture11 min read

Real-Time Inventory: WebSocket and Pub-Sub Architecture

How to build real-time inventory tracking with WebSockets and pub-sub, the patterns that keep stock counts live across warehouses, and the pitfalls to avoid.

WebSocketSocket.ioReal-TimeWMSSystem Design
Real-Time Inventory: WebSocket and Pub-Sub Architecture
On this page13 sections

Part of the Scalable WMS Architecture guide. This deep-dive expands on the real-time inventory section of the pillar.

When two pickers reach for the last unit of the same SKU at the same second, the system that updates fastest wins, and the slower one shows a number that was already wrong by the time it rendered. Real-time inventory is not a luxury feature on a modern WMS. It is what stops oversells, keeps a multi-warehouse view honest, and lets a dashboard reflect the floor instead of a snapshot from thirty seconds ago. This post covers how to build that real-time layer with WebSockets and a pub-sub pattern, drawing on the same architecture we run in production on our own platform.

Why polling is not enough

The instinct is to poll. Have the client ask the server "what changed" every few seconds. It is simple, and for a single warehouse with light traffic it can limp along. It also wastes most of its requests, because the vast majority return "nothing changed," and it builds latency directly into the design: the average delay before a user sees a change is half your polling interval. Shorten the interval to feel live and you multiply the load. Lengthen it to save load and the data feels stale. You cannot win that trade with polling, which is why live operations move to a push model.

A WebSocket flips the relationship. Instead of the client repeatedly asking, the server holds an open, bidirectional connection and pushes changes the instant they happen. One connection, used only when there is something to say. For inventory that changes hundreds of times a minute across a busy floor, this is the difference between a system that feels alive and one that feels like a report.

The pattern we run in production

On our own RMS platform we run a Socket.io layer in exactly this shape. The server is authoritative: clients do not broadcast business changes to each other, the server emits events to clients when state changes, and the client's job is to listen and update its view. Server-emitted events in that system include things like NewNotification and SalarySlipsTracking, each carrying a typed payload, while the only things the client emits are lightweight telemetry signals. That direction of flow is the single most important design decision in a real-time system, and it is worth stating plainly: the server is the source of truth, and the socket is a delivery mechanism, never a place where clients negotiate state between themselves.

Translate that to a warehouse and the events become StockAdjusted, OrderPicked, ShipmentDispatched, LocationTransferred. A scan on a handheld device hits the server, the server validates and commits the change to the inventory ledger, and then, as a consequence of that commit, the server emits an event to every client that cares. The picker's screen, the supervisor's dashboard, and the analytics feed all update from the same authoritative event. Nobody is polling, and nobody trusts a client to have told the truth.

Rooms and channels: don't broadcast everything to everyone

The naive real-time system sends every event to every connected client and falls over the moment it grows. The fix is scoping, and Socket.io calls the primitive a "room." A client joins only the rooms relevant to it, and the server emits to a room rather than to the whole fleet.

For a multi-warehouse operation, the natural scoping is the warehouse itself, often refined further:

  • A room per warehouse, so a picker in the Dallas facility never receives Phoenix's stock events.
  • A room per zone or aisle for high-density floors, so a handheld only hears about the area its operator is working.
  • A room per dashboard view, so an executive watching network-wide totals subscribes to an aggregated stream rather than the raw firehose.

This scoping is what makes the design scale. The cost of a real-time system is not the number of connected clients, it is the number of messages multiplied by the number of recipients. Rooms cut the recipient count to the people who actually need each message.

Pub-sub and scaling across servers

A single server process can hold a lot of WebSocket connections, but a serious deployment runs more than one, and the moment you do, a problem appears: a stock event committed on server A has to reach a picker whose socket is connected to server B. The two processes do not share memory, so an event emitted locally on A never reaches B's clients.

The pub-sub pattern solves this. The servers do not talk to clients across the boundary directly. Instead they publish events to a shared broker, and every server subscribes to it. When A commits a change, it publishes to the broker, the broker fans the message out to all subscribed servers, and each server emits to its own locally connected room members. Socket.io formalizes this with an "adapter," most commonly backed by Redis, where Redis is the pub-sub backbone that keeps every server's view of events consistent. This is the standard way to scale Socket.io horizontally, and it is the piece teams most often forget until their second server makes half the updates disappear.

 handheld scan
      │
      ▼
 ┌─────────┐   publish    ┌──────────────┐   fan-out   ┌─────────┐
 │ Server A │ ──────────► │  Pub-Sub      │ ──────────► │ Server B │
 └────┬────┘             │  broker       │             └────┬────┘
      │ emit to room      └──────────────┘              emit to room
      ▼                                                      ▼
 clients on A                                          clients on B

Reliability: the internet is not your friend

A demo works because the network is perfect. Production is not. The patterns that separate a real real-time system from a fragile one are all about what happens when the connection is not ideal.

Reconnection and resync. Connections drop, especially on warehouse floors thick with metal and dead zones. When a client reconnects it must not assume it has the latest state, because it may have missed events while offline. The reliable pattern is to fetch a fresh snapshot of current state on reconnect, then resume the live stream, so a missed event window self-heals instead of leaving a quietly wrong number on screen.

Backpressure. A burst of activity can produce events faster than a client can process them. Without a guard, the client's queue grows until the tab chokes. Batching events over a short window, or coalescing many updates to the same SKU into its latest value, keeps a busy floor from drowning the UI.

Offline tolerance. Handhelds lose signal. A robust client queues the operator's actions locally and replays them to the server on reconnect, where the server, still the authority, validates each one against current state before committing. This is also why the server, not the client, must own conflict resolution.

Authentication on the socket. A WebSocket needs the same access control as any other endpoint. Authenticate the connection on handshake, and authorize room joins so a user cannot subscribe to a warehouse they have no rights to see.

When a WebSocket is more than you need

It would be dishonest to claim every live feature needs a full bidirectional socket. If the data only flows one way, server to client, and you do not need the client to push, Server-Sent Events are a simpler transport that rides ordinary HTTP and reconnects automatically. A read-only stock ticker on a wall display is a fine candidate. The moment you need the client to send (scans, actions, acknowledgements) over the same low-latency channel, WebSockets are the right tool. We reach for the socket when the floor is interactive and for the lighter option when a screen only observes.

From the author. "The mistake I see most often is treating the socket as the source of truth. It is not. On our platform the server owns state, commits it, and only then emits, so a dropped connection or a malicious client can never corrupt the count. Get that direction right, scope your events into rooms, and put a real broker behind multiple servers, and a real-time warehouse view stops being scary and starts being boring, which is exactly what you want from infrastructure."

Nirmal J, Team Lead, WMS and Inventory Systems at Rorix Technologies

Where this fits

Real-time delivery is one layer of a scalable warehouse system, and it leans on the others. The events you push are the same events worth storing for audit and traceability, and the database behind the ledger has to handle the concurrent writes those scans produce, which is part of the PostgreSQL versus MongoDB decision. For how the real-time layer fits alongside the database, integration, and deployment choices, see the Scalable WMS Architecture guide. The principle to carry over from this post: push, do not poll; keep the server authoritative; scope with rooms; scale with pub-sub; and design for the network you actually have, not the one in the demo.

Frequently Asked Questions

What is the difference between WebSockets and Socket.io for inventory tracking?

A WebSocket is the low-level browser protocol for a persistent, bidirectional connection. Socket.io is a library built on top of it that adds the things a production system needs anyway: automatic reconnection, rooms for scoping events, fallbacks when a raw WebSocket cannot connect, and an adapter for scaling across multiple servers. For inventory tracking you almost always want those features, which is why we run Socket.io rather than raw WebSockets on our own platform.

How do you keep inventory consistent when a connection drops mid-update?

The server stays authoritative and the client never assumes it is in sync after a reconnect. When a client reconnects, it fetches a fresh snapshot of current state and then resumes the live event stream, so any events missed while offline are corrected by the snapshot. Actions the operator took while offline are queued locally and replayed to the server, which validates each one against current state before committing, so a dropped connection self-heals instead of leaving a wrong count on screen.

Can a WebSocket architecture handle multiple warehouses?

Yes, and scoping is what makes it scale. You give each warehouse, and often each zone, its own room, so a client only receives the events relevant to where it is working rather than every event in the network. To run more than one server behind that, you put a pub-sub broker such as Redis between the servers so an event committed on one server reaches clients connected to another. That combination of rooms plus a broker is the standard way to scale real-time across many sites.

Do I need WebSockets, or are Server-Sent Events enough?

It depends on direction. If data only flows one way, from server to client, such as a read-only stock display, Server-Sent Events are simpler and reconnect automatically over plain HTTP. If the client also needs to send over the same low-latency channel, such as scans, actions, or acknowledgements, WebSockets are the right choice. Many warehouse systems end up with WebSockets because the floor is interactive, but it is worth using the lighter option for screens that only observe.

How many concurrent connections can a real-time inventory system support?

A single modern server process can hold tens of thousands of idle connections, so raw connection count is rarely the first limit. The real constraint is message volume multiplied by recipients, which is why scoping events into rooms matters so much. When you outgrow one process you scale horizontally with a pub-sub adapter, adding servers behind the broker, so capacity grows with the number of servers rather than being capped by any single one.

Work with Rorix

Building this into a live warehouse system?

Bring the constraint you keep hitting and a named engineer will walk the design with you.

Written by

Team Lead, WMS & Inventory Systems, Rorix Technologies

Nirmal leads WMS and inventory software delivery at Rorix, from warehouse picking and stock control to real-time inventory tracking and fulfilment workflows. He manages project timelines, stakeholder alignment, and sprint execution, ensuring production-ready systems are delivered on time and keep operations running without disruption.

View full profile

Related articles