Stock Trading System Design Interview Guide
Design a stock trading platform for system design interviews. Covers order placement, matching engine, order book, market data, risk checks, settlement, consistency, scaling, recovery, and trade-offs.
A stock trading system allows users to place buy and sell orders for financial instruments such as stocks, ETFs, and derivatives. In a system design interview, this problem tests your ability to reason about low latency, high throughput, strict ordering, fairness, consistency, durability, and failure recovery.
The most important part of the design is the matching engine. It maintains the order book and matches buy and sell orders using price-time priority. Everything else exists to safely receive orders, validate risk, persist events, publish market data, and settle completed trades.
Interview Scope
For a 45 to 60 minute interview, do not try to design an entire global exchange. Keep the scope focused:
- User authentication and trading account access
- Place buy and sell orders
- Support market and limit orders
- Cancel open orders
- Match orders using price-time priority
- Maintain order book per symbol
- Execute trades
- Publish real-time market data
- Track user cash and stock positions
- Persist orders, trades, and audit logs
Out of scope unless the interviewer asks:
- Options and derivatives
- Margin trading
- Short selling
- Multi-exchange smart order routing
- Full clearing-house implementation
- Tax reporting
- Broker-dealer regulatory workflows
Requirements
Functional Requirements
The system should support:
- Place a limit buy order
- Place a limit sell order
- Place a market buy or sell order
- Cancel an open order
- View order status
- View user's portfolio and positions
- View current order book for a symbol
- Stream real-time trades and price updates
- Run pre-trade risk checks
- Persist completed trades for settlement and audit
Non-Functional Requirements
The system must provide:
- Low latency order matching
- High throughput during market open and close
- Strict ordering for orders of the same symbol
- Price-time fairness
- Strong consistency for order state, positions, and balances
- Durable event log for replay and recovery
- High availability during trading hours
- Complete auditability
- Secure customer and account access
Capacity Estimates
Use rough estimates to guide the design:
| Metric | Estimate |
|---|---|
| Registered users | 20 million |
| Daily active traders | 1 million |
| Tradable symbols | 10,000 |
| Peak order rate | 100,000 orders/sec |
| Average order rate | 20,000 orders/sec |
| Peak market data subscribers | 5 million |
| Trading day | 6.5 hours |
| Daily orders | 300 million to 500 million |
| Daily trades | 50 million to 100 million |
Reads for market data are much larger than writes. Matching writes are smaller but require strict ordering and correctness.
Core Concepts
Order
An order is a user's instruction to buy or sell a symbol.
Common fields:
- order_id
- user_id
- account_id
- symbol
- side: buy or sell
- order_type: market or limit
- quantity
- limit_price
- status
- sequence_number
- created_at
Order Book
An order book stores active buy and sell orders for a symbol.
- Bids are buy orders, sorted by highest price first.
- Asks are sell orders, sorted by lowest price first.
- Orders at the same price are matched by arrival time.
Price-Time Priority
Matching rules:
- Highest bid gets priority among buyers.
- Lowest ask gets priority among sellers.
- If prices are equal, earlier order wins.
Trade
A trade is created when a buy order and sell order match. It records the executed price, quantity, buyer, seller, and timestamp.
High-Level Architecture
flowchart TD
Client["Trading App / API Client"] --> Gateway["API Gateway"]
Gateway --> Auth["Auth Service"]
Gateway --> OMS["Order Management Service"]
OMS --> Risk["Risk Check Service"]
OMS --> Sequencer["Order Sequencer"]
Sequencer --> Router["Symbol Router"]
Router --> MatchA["Matching Engine: AAPL"]
Router --> MatchB["Matching Engine: MSFT"]
Router --> MatchN["Matching Engine: Symbol Group N"]
MatchA --> EventLog[("Durable Event Log")]
MatchB --> EventLog
MatchN --> EventLog
MatchA --> TradeStore[("Trade Store")]
MatchB --> TradeStore
MatchN --> TradeStore
EventLog --> MarketData["Market Data Publisher"]
EventLog --> Portfolio["Portfolio Service"]
EventLog --> Settlement["Settlement Service"]
EventLog --> Audit["Audit and Compliance"]
MarketData --> WS["WebSocket / Streaming Gateway"]
WS --> Client
Main Services
API Gateway
Responsibilities:
- Accept trading API requests
- Enforce TLS and authentication
- Apply rate limits
- Add correlation IDs
- Forward valid requests to the order management layer
Order Management Service
Responsibilities:
- Validate order payload
- Check symbol availability and market hours
- Create order ID
- Track order lifecycle
- Forward accepted orders to risk checks and sequencer
Risk Check Service
Responsibilities:
- Verify user has enough cash for buy orders
- Verify user has enough shares for sell orders
- Check account restrictions
- Enforce max order size and daily limits
- Reject abnormal or suspicious orders
Order Sequencer
Responsibilities:
- Assign monotonically increasing sequence numbers
- Preserve deterministic ordering
- Ensure every matching engine processes orders in the correct order
The sequencer is important because distributed systems do not naturally agree on which order arrived first. Sequence numbers make fairness explicit.
Symbol Router
Responsibilities:
- Route each order to the correct matching engine
- Partition symbols across engines
- Keep all orders for one symbol on the same engine
Matching Engine
Responsibilities:
- Maintain in-memory order book
- Match incoming orders
- Generate trades
- Update order status
- Append events to durable log
- Publish execution events
Market Data Publisher
Responsibilities:
- Publish order book updates
- Publish latest trade price
- Publish ticker updates
- Publish candlestick aggregates
- Serve WebSocket and streaming clients
Portfolio Service
Responsibilities:
- Track user cash balance
- Track share positions
- Update available and settled balances
- Provide portfolio view to users
Settlement Service
Responsibilities:
- Process post-trade settlement
- Move cash and shares after trade execution
- Integrate with clearing and depository systems
- Reconcile completed trades
Data Model
Order
| Field | Notes |
|---|---|
| order_id | Unique ID |
| account_id | Trading account |
| symbol | Stock symbol |
| side | BUY or SELL |
| order_type | MARKET or LIMIT |
| quantity | Original quantity |
| remaining_quantity | Unfilled quantity |
| limit_price | Required for limit orders |
| status | NEW, PARTIALLY_FILLED, FILLED, CANCELLED, REJECTED |
| sequence_number | Matching order |
| created_at | Request timestamp |
Trade
| Field | Notes |
|---|---|
| trade_id | Unique trade ID |
| symbol | Stock symbol |
| buy_order_id | Matched buy order |
| sell_order_id | Matched sell order |
| buyer_account_id | Buyer |
| seller_account_id | Seller |
| executed_price | Trade price |
| executed_quantity | Filled quantity |
| executed_at | Execution timestamp |
Position
| Field | Notes |
|---|---|
| account_id | Trading account |
| symbol | Stock symbol |
| available_quantity | Shares available to sell |
| reserved_quantity | Shares reserved by open sell orders |
| average_price | Average cost basis |
Cash Balance
| Field | Notes |
|---|---|
| account_id | Trading account |
| available_cash | Cash available for orders |
| reserved_cash | Cash reserved by open buy orders |
| settled_cash | Cash after settlement |
API Design
Place Order
POST /v1/orders
Authorization: Bearer <token>
Idempotency-Key: 3cc2a40d-7b7f-4d43-8f41-455719fd67a2
Content-Type: application/json
{
"accountId": "acct_123",
"symbol": "AAPL",
"side": "BUY",
"type": "LIMIT",
"quantity": 100,
"limitPrice": "190.50"
}
Response:
{
"orderId": "ord_789",
"status": "ACCEPTED"
}
Cancel Order
DELETE /v1/orders/{orderId}
Authorization: Bearer <token>
Get Order Book
GET /v1/market-data/AAPL/order-book?depth=10
Response:
{
"symbol": "AAPL",
"bids": [
{ "price": "190.45", "quantity": 1200 }
],
"asks": [
{ "price": "190.50", "quantity": 900 }
]
}
Order Placement Flow
sequenceDiagram
participant Client
participant Gateway
participant OMS
participant Risk
participant Sequencer
participant Engine as Matching Engine
participant Log as Event Log
participant Stream as Market Data
Client->>Gateway: POST /orders
Gateway->>OMS: Validate request
OMS->>Risk: Check cash/position/limits
Risk-->>OMS: Approved
OMS->>Sequencer: Assign sequence number
Sequencer->>Engine: Forward sequenced order
Engine->>Engine: Match against order book
Engine->>Log: Append order/trade events
Engine-->>OMS: Accepted or executed
Log->>Stream: Publish market data events
OMS-->>Client: Order status
Matching Engine Design
The matching engine should be single-threaded per symbol or symbol partition. This sounds limiting, but it makes ordering deterministic and avoids race conditions inside the order book.
Each symbol has:
- Buy side book: max heap or ordered map by price descending
- Sell side book: min heap or ordered map by price ascending
- FIFO queue of orders at each price level
- Order lookup map for cancellation
Limit Buy Example
Incoming order:
BUY 100 AAPL @ 190.50
Current asks:
| Price | Quantity |
|---|---|
| 190.40 | 40 |
| 190.50 | 80 |
| 190.60 | 100 |
Matching result:
- Buy 40 at 190.40
- Buy 60 at 190.50
- Remaining incoming quantity is 0
- Order is FILLED
The trade price is usually the resting order's price, depending on exchange rules.
Market Order vs Limit Order
| Type | Behavior |
|---|---|
| Market order | Execute immediately at best available prices |
| Limit order | Execute only at the limit price or better |
Market orders can walk the book and fill at multiple prices. If the book has low liquidity, market orders can produce bad execution prices. This is why exchanges and brokers often add risk controls.
Cancellation Flow
Cancellation must also go through the sequencer. If a cancel request and a matching order arrive around the same time, sequence order decides the outcome.
Example:
- Order
O1rests in the book. - Cancel request
C1receives sequence105. - Incoming matching order
O2receives sequence106. - Matching engine processes
C1first. O1is cancelled and cannot match withO2.
This preserves fairness and makes behavior replayable.
Consistency and Durability
The system should persist every order event and trade event.
Use an append-only event log:
- OrderAccepted
- OrderRejected
- OrderPartiallyFilled
- OrderFilled
- OrderCancelled
- TradeExecuted
The matching engine can rebuild the order book by replaying the event log from the last snapshot.
Recommended approach:
- Keep order book in memory for low latency.
- Append every event to a durable log.
- Take periodic snapshots of order book state.
- On restart, load latest snapshot and replay events after it.
Partitioning and Scaling
The key scaling rule is simple: all orders for one symbol must go to the same matching engine partition.
Partition options:
| Strategy | Pros | Cons |
|---|---|---|
| One symbol per engine | Simple and fair | Too many small engines |
| Symbol group per engine | Practical and efficient | Hot symbols can overload a partition |
| Dynamic symbol reassignment | Better load balancing | Operationally complex |
Hot symbols such as AAPL or TSLA may need dedicated partitions. Less active symbols can be grouped together.
Market Data Scaling
Market data has fan-out pressure. Millions of clients may subscribe to the same popular symbols.
Design:
- Matching engine emits trade and book update events
- Market data service consumes events
- Aggregates updates by symbol
- Publishes via WebSocket, Server-Sent Events, or streaming protocol
- Uses regional edge gateways for fan-out
- Sends snapshots plus incremental updates
Clients should be able to recover if they miss an update:
- Subscribe to stream.
- Receive snapshot with sequence number.
- Apply incremental updates in sequence.
- If a gap is detected, request a fresh snapshot.
Risk Controls
Trading platforms need guardrails:
- Cash balance check before buy order
- Position check before sell order
- Max order quantity
- Max order notional value
- Price band validation
- Fat-finger protection
- Account restrictions
- Trading halt support
- Symbol-level circuit breakers
Risk checks should happen before the order reaches the matching engine. Some exchange-level controls also happen inside or near the matching layer.
Settlement
Trade execution and settlement are different.
- Execution means buyer and seller matched at a price.
- Settlement means shares and money are legally exchanged.
For many equity markets, settlement can happen later through clearing systems. In the platform:
- Reserve buyer cash before order placement
- Reserve seller shares before sell order placement
- On execution, update pending positions
- On settlement, move to settled positions and cash
- Reconcile with clearing system reports
Failure Scenarios
| Failure | Handling |
|---|---|
| Client retries place order | Use idempotency key |
| Matching engine crashes | Recover from snapshot plus event log |
| Market data stream drops | Client reloads snapshot and resumes from sequence |
| Risk service unavailable | Reject or fail closed for safety |
| Database write is slow | Keep matching path event-log optimized |
| Hot symbol overloads engine | Move hot symbol to dedicated partition |
| Duplicate event delivery | Consumers must be idempotent |
| Settlement mismatch | Reconciliation workflow and manual review |
Security
Security requirements:
- TLS everywhere
- Strong customer authentication
- MFA for sensitive account actions
- Fine-grained account authorization
- Signed service-to-service requests
- Audit logs for all order and account actions
- Secrets managed through KMS
- PII encryption and masking
- Rate limits and bot protection
Observability
Track:
- Order acceptance latency
- Matching latency p50, p95, p99
- Orders per second by symbol
- Trades per second by symbol
- Order rejection rate
- Cancel success rate
- Market data publish lag
- Event log append latency
- Matching engine restart time
- Snapshot replay time
- Settlement mismatch count
Every order should have:
- correlation_id
- order_id
- account_id
- symbol
- sequence_number
- matching_partition
Trade-Offs
Single-Threaded Matching vs Parallel Matching
Single-threaded matching per symbol is easier to reason about and preserves deterministic ordering. Parallel matching can improve throughput but makes fairness and replay much harder.
For an interview, choose single-threaded per symbol partition first, then scale by partitioning symbols.
In-Memory Order Book vs Database Order Book
An in-memory book is fast enough for trading. A database-backed book is simpler but too slow for high-throughput matching.
Use memory for live matching and durable logs/snapshots for recovery.
Strong Ordering vs Availability
During trading, correctness and fairness are more important than accepting every request. If the sequencer or matching partition is unavailable, it is safer to pause a symbol than to process orders out of order.
Interview Walkthrough
Use this structure:
- Clarify scope: market orders, limit orders, cancel, market data.
- State non-functional requirements: low latency, throughput, fairness, durability.
- Estimate orders per second, daily orders, and subscribers.
- Draw the architecture.
- Deep dive into order book and matching engine.
- Explain price-time priority.
- Explain sequencer and symbol partitioning.
- Cover persistence using event log and snapshots.
- Cover market data fan-out.
- Discuss risk checks, settlement, and failure recovery.
Common Interview Mistakes
- Matching orders directly in a relational database
- Ignoring price-time priority
- Not sequencing cancel requests
- Letting all symbols share one matching engine forever
- Forgetting market data fan-out
- Ignoring idempotency for order placement
- Confusing trade execution with settlement
- Not explaining recovery after matching engine crash
- Using async processing where strict order is required
Final Design Summary
A strong stock trading design should use:
- API Gateway for trading clients
- Order Management Service for validation and lifecycle
- Risk Check Service before matching
- Sequencer for deterministic order
- Symbol Router for partitioning
- In-memory Matching Engine per symbol or symbol group
- Append-only event log for durability
- Snapshots for fast recovery
- Market Data Publisher for real-time streams
- Portfolio and Settlement services for post-trade processing
- Observability and audit logs across the full order lifecycle
The most important interview point is this: keep matching deterministic. Once the order sequence is clear and replayable, the rest of the trading platform can scale around it.