Tech Nuances™
Tech Nuances Insights

Trading Platform Architecture

In-depth view of trading platform.

Published September 24, 2026

Following a single limit order from the trading screen to the exchange and back to a verified account

The Systems Behind a Trade

A user opens a trading app, looks at a quoted price, and places a limit order to buy 100 shares. A limit order is an instruction to trade only at a stated price or better, so it may wait in the market rather than trading straight away. Forty shares execute and sixty remain open. The price begins to move, the user decides against buying the rest, and taps Cancel. A moment later, before any answer comes back, the phone loses its network connection. When the app returns, the user wants one thing: a trustworthy answer about what actually happened to the money and the shares.

That short sequence touches almost every interesting problem in trading platform design. It involves a price that was already slightly out of date by the time it was rendered. It involves money that had to be set aside before anyone knew whether the order would trade. It involves a cancellation whose outcome the market settled while the user's app was offline and unable to receive the answer. This article follows that order end to end, and the question it keeps returning to is not how fast is the system but what can the platform prove about the state of the order and the account at any given moment.

This is the platform architecture that the rest of the article works through. Notice the three ownership zones, and that traffic crosses between them on three separate routes rather than through a single channel. Both are explained below.

The client, the broker, and the exchange

A trade passes through the hands of the client, the broker, and the exchange, and each of them owns a different part of the work. Keeping those responsibilities straight makes the rest of the article much easier to follow.

  • The client is the mobile or web application the user touches. It owns presentation, local caching of recent prices, and the user's session. It owns no authoritative truth at all. Anything the app displays is a copy of state that lives somewhere else, and the age of that copy is a design concern rather than a detail.
  • The broker owns the largest share of the architecture and carries most of the obligations. Broker services authenticate the user, check that the order is permitted, reserve the funds, give the order a durable identity, forward it to the market, interpret what comes back, and maintain the account records that the user and the regulator will later rely on. The broker also runs the market-data pipeline that feeds prices to the app, and the order gateway, meaning the broker-side component that speaks the exchange's own wire protocol and holds the connection session with the exchange.
  • The exchange owns the market itself. Its matching infrastructure decides which orders trade, in what order, and at what price, and its decisions are final in a way that no broker record can override. An exchange is one kind of trading venue, which is the general term for any place where an order can be executed. Other kinds exist, and a large broker may route orders to several of them, but this article follows a single exchange from start to finish. The exchange also publishes market data and returns execution reports, the messages that tell the broker an order was accepted, rejected, partially filled, fully filled, or cancelled. Behind the exchange sit the post-trade interfaces of the clearing house, which is the institution that stands between buyer and seller and sees the trade through to settlement. The broker connects to those interfaces too, on a slower cycle.

Authority between those owners is worth settling before anything else. The exchange's execution reports and the clearing house's records describe what happened in the market. The broker's account ledger describes what the user owns and owes. These are separate books that must be made to agree, and when they disagree the exchange and clearing records win. Much of the engineering described later exists to keep those gaps rare, to close them quickly, and to make sure the broker can see one as soon as it appears.

The paths through the platform

It is tempting to draw a trading platform as a single pipe running from the app to the exchange and back. That picture hides the most important property of the system, which is that traffic travels three distinct routes with three different delivery requirements.

  • The market-data path runs one way, from the exchange into the broker's pipeline and outward to every subscribed app. It is high volume, it is the same content for every recipient, and it tolerates the loss of intermediate values as long as the app ends up showing the current one.
  • The order-submission path runs the other way, from a single user to a single exchange. It is low volume by comparison, but each message is unique and financially binding, so losing one or sending one twice is unacceptable.
  • The execution-reporting path runs back from the exchange to the broker and then to the user. It is low volume like order submission, and it carries the same intolerance of loss or duplication, but it is asynchronous. Reports arrive when the market produces them, whether or not the user is watching.

Keeping the three paths separate is not a diagramming preference. It drives capacity planning, because a burst of quotes must never be allowed to slow order submission. It drives protocol choice, because a dropped quote is recoverable while a dropped execution report is not. It also drives the recovery story at the end of this article, where the app reconnects and has to repair its view of prices and its view of the order using two completely different mechanisms.

With the parties and the routes established, the natural place to start following the order is before the order exists, at the price the user was looking at when the decision was made.

From Market Data to the Trading Screen

The price on the screen belongs to an instrument, meaning one tradable item such as a single company's shares, a bond, or a futures contract. That price is the beginning of the trade, and it is already a little bit historical. The exchange published it, the broker's pipeline received and reshaped it, a fan-out service delivered it, and the app rendered it. Each of those stages adds delay. The design problem is not only to keep the total delay small. It is to make sure the app can tell the difference between a price that is current, a price that is merely old, and a price that is wrong because updates were silently missed.

Feed ingestion and distribution

Notice that everything between the exchange stream and the apps happens inside the broker, and that the traffic changes shape at the fan-out stage: one update arriving from the exchange becomes a delivery to every app subscribed to that instrument, and no delivery at all to the apps that have not subscribed.

Ingestion is the point where the broker receives the exchange's published stream. The feed arrives in the exchange's own binary format, usually over a multicast network group, and the first job is instrument identification. Each exchange names an instrument in its own way, using a numeric code or a ticker symbol that means nothing outside that exchange, and the broker has to map that code onto the identifier it uses for the same instrument across its own systems. Getting this mapping wrong is not a cosmetic error. It puts one company's price on another company's screen, and the mapping has to survive reference-data changes such as a ticker symbol being reassigned or a corporate action like a share split.

Normalization follows. Exchanges differ from one another in how they express prices, quantities, timestamps, and trade conditions, and a broker that connects to more than one of them should not force every downstream service to know which exchange a quote came from. The ingestion layer converts each update into one internal representation, attaches the exchange's own timestamp alongside the broker's receipt timestamp, and passes it on. Keeping both timestamps costs a few bytes and pays for itself later, because the difference between them is the only honest measure of how long the broker took.

Distribution is where the shape of the traffic changes completely. The broker receives one update for a popular instrument and may have to deliver it to a very large number of connected apps. A single incoming message becomes many outgoing messages, and the multiplier is set by how many users are watching that instrument at that moment. This is why the fan-out service maintains a subscription for each connection, meaning the explicit list of instruments that particular app has asked for. Without subscription filtering the broker would push every instrument to every client, spending bandwidth on prices nobody is looking at and forcing mobile devices to parse messages they will discard.

A cache sits between ingestion and fan-out, holding the latest known state for every instrument. It exists mainly so that a newly subscribing app can be given a complete starting picture immediately instead of waiting for the next update, which for a thinly traded instrument might be minutes away. The cache also absorbs the difference in pace between a feed that can burst and a mobile connection that cannot.

Freshness and feed integrity

Most exchange feeds are built from two kinds of message.

  • A snapshot is a complete statement of the current state of an instrument.
  • An incremental update, often called a delta, describes only what changed since the previous message.

Incremental updates carry a sequence number, and the receiver is expected to apply them strictly in order. If sequence number 41 arrives after 39, message 40 is missing and the receiver's picture is no longer reliable. The correct response is defined by the exchange's feed contract, and it usually means requesting a fresh snapshot, or switching to a secondary feed, and then replaying the buffered increments on top of the snapshot until the stream is aligned again.

Notice that the receiver cannot simply carry on after a missing message. Alignment is only restored by taking a fresh snapshot and replaying the buffered increments on top of it.

What the broker may do with those increments depends on what the screen is showing. A simple latest-price display can safely coalesce updates, which means discarding intermediate values and sending only the most recent one when the client is ready to receive. If the price moved five times in the last two hundred milliseconds, the user only needs the fifth value. An order book display is a different matter. An order book is the list of resting buy and sell orders at each price level, and it is reconstructed by applying every delta in sequence. Skip one and the reconstruction is wrong, sometimes subtly and for a long time. So the rule is straightforward: coalesce a display that only needs the newest value, and preserve every delta for a display that is built by accumulation.

A harder question is how to tell a quiet instrument from a broken feed. Both look identical from the app's point of view, because in both cases no updates are arriving. Silence on its own means nothing. The platform needs a positive signal of liveness, which normally comes from a heartbeat message on the feed session and from the pipeline's own health checks, so the age of the last received message can be compared against the age of the last confirmed heartbeat. When a heartbeat is current and the instrument is silent, the instrument is simply not trading. When the heartbeat itself has stopped, or the sequence numbers have a gap that has not yet been repaired, the price on the screen must be marked as stale rather than presented as current.

Notice that the safe treatment of an update depends entirely on what the screen is showing, and that a current heartbeat is what separates an instrument that is not trading from a feed that has failed.

The user has now seen a price that the platform believes is current, and has decided to act on it. The moment the Buy button is pressed, the obligations change entirely, because the platform is no longer distributing public information. It is about to commit the user's money.

Order Entry and Pretrade Risk

Between the Buy button and the exchange, the broker has a short window in which to do several things that cannot be undone afterwards. It has to establish that the request is genuine, that the order is permitted, that the money is available and now spoken for, and that the order has an identity which will survive a crash. All of this happens before anyone knows whether the order will trade, which is what makes it difficult. The broker is committing to an outcome it cannot yet see.

Validation and funds reservation

Authentication confirms who is sending the request, and authorization confirms that this user may trade this account. The two are separate, and conflating them is a common source of security defects in platforms that support joint accounts, advisers, or corporate users. Instrument and market-state validation comes next. The instrument must exist, must be tradable by this account, and the market must be in a session that accepts this kind of order. A limit order sent before the opening auction is a different proposition from the same order sent mid-session, and the broker should reject or queue it deliberately rather than letting the exchange decide.

Pretrade risk checks then apply the limits that protect the user, the broker, and the market: order value ceilings, price bands that catch a mistyped price, quantity limits, position limits, and restrictions on particular instruments. These checks are cheap individually, but they sit directly in the latency path, so they are usually evaluated against data held in memory rather than fetched per order.

The most demanding step is the reservation of funds. Buying power is the amount the account may commit right now, and reserving against it means moving an amount from available to held, so that the same rupee or dollar cannot be committed twice. For a cash purchase the reservation covers the full order value plus expected charges. For a margin account it covers the required margin instead. The reservation is not a payment. It is a claim that will be converted into a settled movement if the order trades, and released if the order is cancelled or expires.

Reservation is also where a subtle failure hides. Consider two orders for the same account arriving a few milliseconds apart, one from a phone and one from a laptop, each large enough to consume most of the available buying power. Either order on its own would pass every check. If both requests read the balance, evaluate the check, and then write their reservation, both read the same balance before either has written anything. Both conclude that the funds are available, and both write a reservation. The account is now committed beyond its buying power, and the broker finds out only when a trade settles.

The remedy is to make the read and the write a single indivisible step for that account, rather than two steps with a gap in between. A conditional update that succeeds only if the balance is still what it was when it was read will cause the second request to fail, and that request can then be retried or rejected. Routing every request for one account through a single owner, so that requests are processed strictly one after another, achieves the same thing. Both approaches serialize activity per account, which adds a small amount of latency and creates a hot spot for an unusually active account. That cost is accepted, because the alternative is an account that has spent money it does not have.

Notice that neither remedy lets both requests reserve funds. The conditional update stops the second one at the balance, and the single owner stops it from arriving at the same time.

Order identity and uncertain submissions

Before the order leaves the broker it is given a client order identifier, a value generated by the broker that uniquely names this order at this exchange. The identifier is written to durable storage together with the order's initial state and the reservation, in one transaction, so that a crash cannot leave a reservation without an order or an order without a reservation.

The app also sends its own request identifier with the submission, which lets the broker recognise a resubmitted request from a user who tapped Buy twice or whose phone retried automatically. The identifiers do different jobs. The request identifier makes the app's call safe to repeat. The client order identifier makes the exchange submission safe to repeat.

That second property matters because the order now crosses a boundary the broker does not control. The order gateway sends the order to the exchange and waits for an acknowledgement. Broker acceptance, exchange acceptance, and execution are easy to blur together and must be kept apart. Broker acceptance means the broker has recorded the order and taken responsibility for it. Exchange acceptance means the exchange has admitted the order to its book. Execution means some or all of the quantity has actually traded. An order can be accepted by the broker and rejected by the exchange. It can be accepted by the exchange and never trade at all.

Notice that the timeout narrows nothing. All four states shown here are consistent with the same silence, and only the exchange can say which one is true.

The hardest moment on this boundary is the one where the order gateway sends the order and no acknowledgement arrives within the timeout. A timeout tells the broker only that no reply came back in time. The order may never have left the gateway, may be sitting in a queue, may have been accepted and be resting in the book, or may already have traded in full. Every one of those possibilities is consistent with the same silence, so a timeout must never be treated as a rejection.

Resending blindly is equally unsafe, because a duplicate order in a moving market can mean the user buys twice. The safe sequence is to move the order into an explicit pending, outcome unknown state in the broker's records, keep the reservation in place, and ask the exchange what it knows, using an order status request or the daily order report keyed by the client order identifier. Because that identifier is unique and is reused on any retry, a resubmission of an order the exchange already holds is rejected as a duplicate rather than creating a second order. Only when the evidence shows that the exchange never received the order should it be sent again.

Uncertainty of this kind is expensive, and its cost rises with how long it lasts. That is one of the reasons platforms invest so heavily in reducing delay and variability on the order path, which is the subject of the next section.

Latency on the Order Path

Delay on the order path takes forms that are worth naming separately. Latency is how long a step takes. Jitter is how much that duration varies from one order to the next. A platform with a modest average and a stable distribution is usually easier to operate, and easier to explain to users, than one with a lower average and occasional long stalls. What follows looks first at where the machines sit, and then at how the delay between them is measured honestly.

Edge placement and exchange connectivity

Notice where each component sits before reading on. Proximity is bought at both ends of the path, but the edge near the user deliberately holds no account state, while the order gateway sits inside the exchange building and the order service stays beside the account ledger.

The user-facing edge is the first point of contact. Terminating the app's encrypted connection close to the user shortens the handshake and the round trips that follow, which is a real improvement for a phone on a mobile network. What the edge must not do is run the decision-making. Pretrade risk and funds reservation need the authoritative account state, and that state lives in one place. Spreading it across edge locations to save a few milliseconds recreates the double-reservation problem from the previous section on a much larger scale. The practical arrangement is a thin edge that handles connection, session, and routing, placed anywhere convenient, and an order service placed next to the account records.

At the other end of the path, exchanges sell physical proximity. Co-location means placing the broker's own servers inside the exchange's data centre, so that the distance between the order gateway and the matching engine is measured in metres of cable rather than in kilometres of network.

Nasdaq's co-location page describes the service as letting participants reduce latency and network complexity by using a single hand-off to reach all its markets, and states, in its current published specification, that round-trip order-to-acknowledgement and market-data order-to-tick latency over its high-speed 10G Ethernet network is under fifty microseconds.

The National Stock Exchange of India's co-location facility page sets out a comparable offering, listing rack variants from a quarter rack up to a high power density rack, each with a published annual charge and a maximum permissible number of interactive connections. Those published figures describe the exchange's own infrastructure. They say nothing about how long the broker's software takes once the packet arrives, which is usually the larger and more controllable number.

Between the edge and the exchange, every additional service hop costs something. A request that passes through an authentication service, a risk service, a position service, and a gateway pays four queueing delays and four serialization costs, and the slowest of the four sets the pace under load. Reducing hops on the order path is usually worth more than optimising any single hop.

Capacity is another word that hides distinct meanings, and confusing them sends people to the wrong fix. Bandwidth is how many bytes a link can carry, and it constrains the market-data path far more than the order path. Event-processing capacity is how many messages the broker's own services can handle per second, and it is bounded by software design rather than by cable.

A further limit on capacity sits outside the broker altogether. The permitted upstream message rate is a contractual ceiling set by the exchange on how many messages a member may send, and exceeding it results in throttling or disconnection regardless of how much bandwidth is free. A platform can be well within its bandwidth, comfortable on processing, and still be blocked by the exchange's message-rate limit.

Measuring the complete latency path

None of this means anything without measurement, and a latency number is meaningless until its two ends are stated. The useful intervals on this path are app submission to broker acceptance, broker acceptance to exchange acknowledgement, and exchange acknowledgement to the first execution report reaching the account ledger. Each interval has a different owner and a different remedy, and reporting them as a single total hides which part actually moved.

Averages are the wrong summary for this kind of work, because a mean hides the slow tail, and the slow tail is where users lose money and support tickets are created. The ninety-fifth and ninety-ninth percentiles describe what the unlucky orders experienced, and they should be measured during a realistic burst rather than at a quiet moment, when the figures describe empty queues instead of the open. Clock discipline matters as well. An interval that starts on one machine and ends on another is only as good as the agreement between the two clocks, so it should be treated as approximate unless those hosts are properly synchronised.

Interpretation matters as much as instrumentation. Time spent waiting for a match is not a performance problem. A limit order that rests in the book for ninety seconds before trading was not delayed by the platform, it was waiting for the market to come to its price. Processing delay belongs to the engineers, and waiting time belongs to the market. A dashboard that adds the two together will send people hunting for a bottleneck that does not exist, and will hide a real regression behind a quiet trading session.

Notice that each engineering span has a named start and end on the same path, and that the market waiting span is deliberately kept outside the platform's latency budget.

The order has now reached the exchange as quickly as the platform can manage, and the waiting begins. What comes back is no longer about speed at all. It is about getting the account to agree with the market.

Execution and Account Correctness

Once the exchange holds the order, the broker becomes a listener. It no longer decides anything about the trade. Its job is to receive each execution report, apply it to the order's state and to the account, and make sure that the result it shows the user is the result the market actually produced. This sounds mechanical, and most of the time it is. The difficulty comes from the fact that reports arrive asynchronously, in a sequence the broker does not choose, and sometimes while the broker is in the middle of doing something else to the same order.

Matching and order state changes

The exchange's matching engine keeps the order book introduced earlier and applies a published rule to decide which resting order trades first. The common rule is price-time priority. A better price always wins, and among orders at the same price the one that arrived earlier wins. That rule is the reason a queue position has value, and the reason a few microseconds on the order path can change whether an order trades at all in a fast-moving market.

A limit order rarely trades in one clean event. The user's order for 100 shares meets whatever quantity happens to be available at an acceptable price, and the exchange sends a partial fill for the quantity that traded. Forty shares execute, and the order's state becomes partially filled with sixty shares still working. Further fills may follow in any number of pieces, at prices that need not be identical, so the broker has to track two running totals for every order: the filled quantity and the average execution price weighted by the quantity of each fill. Showing a single price for a multi-fill order without weighting it is a small arithmetic mistake that produces a wrong profit-and-loss figure and a support call.

Execution reports also carry their own ordering information, because the network can deliver them out of sequence and a gateway that reconnects may replay reports the broker has already applied. Each report should therefore be applied only once, and applied in the exchange's stated order rather than the order of arrival. The practical technique is to key every report by its execution identifier, ignore any identifier already recorded, and hold a report that refers to a state the broker has not yet reached until the missing report arrives. Applying the same fill twice credits shares that do not exist.

Timing produces its own class of problem once an order is working, and the order in this article runs straight into it. The user, holding 60 shares still open, taps Cancel at almost the same moment that the exchange matches 25 of those 60 shares. A cancel is a request, never an instruction the broker can honour on its own, because the exchange holds the order and the exchange decides. While the request is in flight the broker should show the order as cancellation requested with 60 shares still working, and it must not show the order as cancelled or release any part of the reservation.

The outcome is then whatever the exchange reports. The cancel may win, leaving the order cancelled with 40 shares filled in total. The match may win outright for the whole remaining quantity, leaving the order fully filled and the cancel rejected as too late. Here the match takes 25 shares and the cancel then removes the remaining 35, so the order ends with 65 shares bought and 35 cancelled. Whichever it is, the broker waits for the report and applies it. The reservation is settled for the quantity that actually traded, at the prices that actually traded, and only the unused remainder is released back to buying power. Releasing funds when the cancel is sent, rather than when the exchange confirms it, is what creates an account that has spent money it has already given back.

Notice that every transition is caused by a message from the exchange rather than by the user, and that the unused part of the reservation is only released at the final state.

Records and reconciliation

The account ledger is the broker's record of what the user owns and owes, and it is best kept as an append-only sequence of entries rather than a set of balances that get overwritten. Each execution report produces entries that are written once and never edited, and the current balance is derived from the entries rather than stored independently of them. A correction is recorded as a further entry that reverses and replaces the earlier one. The reason for this discipline is not bookkeeping tradition. It is that a balance which is only ever computed from an immutable history can always be explained, and a balance that was overwritten cannot.

Each entry should also carry the evidence behind it. Recording the execution identifier, the client order identifier, the exchange's own order identifier, and the exchange's timestamp alongside the amounts means that any line in the ledger can be traced back to the specific execution report that caused it. When a user disputes a trade, or a regulator asks how a figure was reached, that link is the whole answer.

This is where the authority rule from the opening section is put into practice. The broker's intraday picture is built from the execution reports it happened to receive. The exchange's end-of-day order and trade files, and the clearing house's records, describe what the market says happened.

Reconciliation is the process of comparing the broker's ledger against those authoritative files and resolving every difference, and it runs after the session closes because that is when the files become available. Differences are expected rather than alarming. A report may have been missed during a gateway restart, a trade may have been amended by the exchange, or a fee may have been calculated differently. What matters is that each difference is found, explained, and corrected with a new ledger entry before the user's statement is produced. A platform that reconciles daily and finds nothing has earned its intraday numbers. A platform that does not reconcile has no way of knowing whether its numbers are right.

The broker now holds a correct and defensible view of the order: 65 shares bought, 35 cancelled, and the unused part of the reservation returned to buying power. The remaining problem is that the user cannot see any of it, because the phone lost its connection moments after the cancel was sent.

Realtime Delivery and Mobile Recovery

Getting information onto a phone is a different engineering problem from getting it across a data centre. The connection is slow, intermittent, and frequently suspended by the operating system when the user switches apps. The platform has to choose how it pushes updates, and it has to assume that the connection will break at the least convenient moment.

Choosing a delivery mechanism

The available mechanisms differ in who initiates the traffic, whether the connection stays open, and whether data can travel in both directions. Those properties decide which parts of the platform each mechanism suits.

MechanismHow it worksWhere it fits in this platform
PollingThe app asks the server for the current state on a fixed timer, and the server answers whatever it knows at that moment.Simple and reliable, but it wastes requests when nothing has changed and adds up to the polling interval of delay when something has. Suitable for slow-moving data such as account summaries, not for live prices.
Long pollingThe app asks and the server holds the request open until something changes or a timeout expires, then the app immediately asks again.Cuts the wasted requests and the delay, at the cost of holding many open requests on the server. A workable fallback when a streaming connection cannot be established.
Server-sent eventsThe app opens one connection and the server streams updates down it continuously. Traffic flows one way only.A good fit for the market-data path, which is one-directional by nature. It carries a built-in mechanism for telling the server the last event the app received, which makes resuming after a drop straightforward.
WebSocketThe app and the server hold one connection open and either side can send at any time.The usual choice when one connection must carry both subscription changes going up and price updates and execution reports coming down. More to operate, because the application has to define its own resumption and heartbeat behaviour.
Push notificationThe broker hands a short message to the platform's notification service, which delivers it to the device even when the app is closed.The only mechanism that reaches a user who is not in the app. Delivery is neither guaranteed nor ordered, so it is a prompt to open the app rather than a channel of record.

The last row carries a point that is easy to get wrong. A fill notification that arrives on the lock screen is convenient, and it is also unverified. The notification service may drop it, delay it, or deliver it out of order, and none of that is visible to the broker. So the notification should tell the user that something happened and invite them to look, while the authoritative quantity and price come from the app asking the broker directly. Putting the final numbers in the notification itself creates a version of the trade that nobody can reconcile.

Recovery after a disconnect

When the phone comes back, the app is holding a view of the world from before the connection dropped, and it has no way of knowing how wrong that view is. The important insight is that the two kinds of stale data on the screen must be repaired in completely different ways, exactly as the three paths in the opening section suggested.

Prices need the current value and nothing else. Whatever the app missed while it was offline is worthless, because those quotes have been superseded. So the app re-subscribes and the broker answers from the latest-state cache described earlier, sending one complete picture per instrument rather than a backlog. Replaying missed quotes would waste the user's bandwidth and show a sequence of prices that no longer exist.

Order events are the opposite. Every execution report that arrived during the gap describes something that genuinely happened to the user's money, and none of it is superseded. The app must therefore tell the broker how far it had got, using the identifier of the last order event it processed, and the broker replays everything after that point in order. Because each event is keyed and applied once, a replay that overlaps with events the app already has is harmless.

Reconnection behaviour needs care as well. The app should reconnect with a delay that grows after each failed attempt, plus a small random offset, so that a broker outage does not end with every phone in the country reconnecting in the same second. Until the replay has completed, the app should also present the order screen as still synchronising rather than as a settled position. A screen that admits it is catching up is far better than one that confidently shows a state it has not yet verified.

That reconnection storm is a reminder that one user's bad moment is usually everyone's bad moment. The same is true of market opens, volatile sessions, and failures inside the broker.

Operating Through Load and Failure

Trading load is not spread evenly through the day. The opening minutes, the closing auction, and any piece of unexpected news produce a spike in both market data and order submissions at the same moment, from users who care more than usual about the outcome. A platform that performs well on an average afternoon and falls over at the open has not been engineered for its actual workload.

Capacity and safe failover

The market-data path and the order path scale in different ways, and treating them as one system wastes money on one and starves the other. Market-data fan-out grows with the number of connected apps and the number of instruments they watch, and it can be scaled by adding servers because no single fan-out server needs to know about any other. The order path does not scale that way, because the funds reservation from the earlier section requires an authoritative view of each account. What can be done is to divide accounts among servers, so that each account has exactly one owner at a time and different accounts are handled in parallel. That keeps the ordering guarantee where it is needed while still allowing the platform to grow.

When capacity runs short anyway, the platform should shed the least important work rather than degrade uniformly. Reducing the update rate on price displays is an acceptable response to a surge. Slowing order submission or execution reporting is not, because those carry the financially binding traffic. Deciding the order of sacrifice in advance, and building it into the code, is what stops that decision being made badly in the middle of an incident.

Failover carries a specific hazard on the order path. The order gateway holds the session with the exchange, and that session has state, including the message sequence numbers the exchange expects.

A standby gateway cannot simply start sending, because the exchange will reject or misinterpret messages that do not follow the established sequence. Worse, if the original gateway is merely slow rather than dead and both are briefly active, the exchange may receive the same order from both, and the exchange has no way of knowing that the two came from one broker that lost track of itself.

Guarding against this means ensuring that only one gateway can hold the exchange session at a time, and that a gateway taking over first recovers the session state and reconciles outstanding orders with the exchange before it sends anything new. The safe order of operations on failover is to find out what is true before acting on it.

Notice that the danger is not a dead gateway but a slow one, and that every step in the safe sequence is a question the standby answers before it sends anything.

Observability and controls

Ordinary infrastructure monitoring tells you that a server is busy. It does not tell you that orders are being accepted and reports are coming back, which is what actually matters here. The signals worth watching are the ones tied to the business of trading: the rate of orders rejected by the exchange, the age of the oldest order still waiting for an acknowledgement, the number of orders sitting in the pending, outcome unknown state, the gap between the exchange's timestamp and the broker's receipt timestamp on the market-data feed, and the count of unreconciled entries from the previous session. Each of these goes wrong before users notice, which is the only useful property a signal can have.

Alongside the signals sit the controls, which are the deliberate ways of stopping trading when something is wrong. A kill switch cancels a firm's working orders and blocks new submissions, and the useful version operates at several levels: one instrument, one account, one strategy, or the whole connection. The value of a kill switch lies in how quickly it can be used, which means it must be reachable by whoever is on duty without a deployment, and it must have been exercised recently enough that nobody hesitates. A control that has never been tested is a control nobody trusts at the moment it is needed.

One more obligation runs underneath all of this. Every order, modification, cancellation, and execution has to be recorded in a form that cannot be altered afterwards, with accurate timestamps, because regulators and dispute processes work from that record. The append-only ledger and the evidence stored with each entry already provide most of it. The remaining requirement is that the audit trail is written on the same transaction as the state change rather than afterwards, so that a crash can never produce a state change with no record of why it happened.

Returning to the Original Order

The order that opened this article can now be followed the whole way. The price the user acted on came from the exchange's feed, was identified and normalized on ingestion, and was delivered through a subscription-aware fan-out service with enough liveness information for the app to know it was current rather than merely recent. The Buy button produced a request that was authenticated, checked against pretrade limits, and backed by a reservation written in the same transaction as the order and its client order identifier. The order gateway sent it to the exchange and the exchange admitted it to the book, where price-time priority matched 40 of the 100 shares.

Then the user tapped Cancel and the phone dropped off the network, and neither event changed what the broker was doing. The cancel request had already reached the exchange, so the exchange decided the outcome in the usual way. An execution report for a further 25 shares arrived on the order gateway, was applied once, and produced ledger entries carrying the execution identifier and the exchange's timestamp. The cancellation of the remaining 35 shares followed, and only then was the unused part of the reservation released. The user's absence was never part of the story, because the account was being maintained from the exchange's reports rather than from anything the app was doing.

When the connection returned, the app repaired its two views separately. Prices were refreshed from the latest-state cache, with no attempt to replay what had been missed. Order events were replayed in order from the last event the app had processed, so the second fill and the cancellation both appeared even though they had happened while the app was offline, and the screen said it was still synchronising until the replay finished. The user was shown 65 shares bought and 35 cancelled. After the close, reconciliation against the exchange and clearing records confirmed that the broker's version of the trade matched the market's version, and any difference would have been corrected with a further ledger entry rather than an edit.

The techniques in this article pull in two directions, and the tension between them is the real subject. Co-location, a thin edge close to the user, and a short chain of services on the order path exist to shorten the window in which the platform does not yet know what happened. Durable identifiers, single-owner accounts, append-only ledgers, and daily reconciliation exist to make sure that whatever happens in that window can still be explained afterwards. Speed reduces the uncertainty. Correctness survives it. A trading platform is judged on the second one, because a user who loses a connection at the wrong moment does not ask how fast the system was. They ask what happened to their order, and the platform has to be able to answer.