A market price looks like a small piece of data, but a trading application has several uses for it. The interface needs a current value, a chart needs historical candles, and order processing may need to evaluate an entirely different set of conditions. Treating those consumers as one operation hides important differences.
My GBT Market work includes separate deployed chart applications alongside the main backend. The source makes a useful boundary explicit: chart processing handles price and history updates; it does not execute margin closure, take-profit/stop-loss handling, or limit orders.
Current state and history are different queries
A current-price read asks for the latest relevant value. A historical-chart request asks for an ordered set of values over a timeframe. The chart applications use Redis for current and cached data and MongoDB for price history. The chart-data service includes retrieval, initialization, and cleanup responsibilities.
That split is about access patterns. Calling Redis fast does not explain which data it owns, how a missing cache is recovered, or what a reader should do when history is incomplete. Those questions remain part of the design even when the components are familiar.
A chart update has several stages
The chart application consumes price-update events, updates price-related data, maintains chart history, and emits information for socket broadcasting. It supports several candle resolutions, from minute-level views to daily history.
Each stage has an observable result. A price can be stored while a client still shows an older value. A client notification can arrive while a historical read is being refreshed. A useful investigation follows the event through those stages instead of treating every stale chart as a WebSocket problem.
A notification is not a financial record
Socket.IO delivers updates to connected clients, and Redis pub/sub supports process communication and fan-out. Those are delivery mechanisms. They do not replace the authoritative records and safeguards used by wallet or order operations.
GBT’s wallet work includes atomic updates, concurrency protection, and duplicate-operation safeguards. A chart broadcast does not prove those invariants, just as a correct wallet balance does not prove that the screen is current. The two paths need related but separate verification.
Separation introduces operational questions
Splitting responsibilities makes them easier to inspect, but it also creates a boundary to operate. The producer and consumer need compatible event meanings. Recovery needs to distinguish current state from historical gaps. A failure in one stage should be diagnosable without assuming the whole product failed in the same way.
The separate applications are confirmed production work. I am not attaching an unmeasured throughput number or an exactly-once delivery guarantee to this account. The source-backed result is the implemented separation of price/chart responsibilities from order execution.
Follow one event before drawing the whole system
For a technical walkthrough, I start with one price update: where it enters, which current value changes, which candle record it affects, and what the client receives. Then I follow a wallet operation separately. Those two traces explain more about the architecture than a diagram containing every database and queue logo.