Detailed Component Design
1. Client Layer
Clients include web apps, mobile apps, trading terminals, and institutional APIs.
Responsibilities:
- Submit orders.
- Cancel orders.
- Subscribe to market data.
- Receive execution reports.
- Configure price and risk alerts.
Reliability considerations:
- Client must send a unique
clientOrderId. - Client must send an
Idempotency-Key for order placement and cancellation. - Client should handle reconnects and replay missed events using sequence numbers.
2. API and WebSocket Gateway
Responsibilities:
- TLS termination.
- Authentication.
- Authorization.
- Request validation.
- WebSocket session management.
- Routing requests to internal services.
Design:
- REST/gRPC for order placement and account APIs.
- WebSocket for market data and execution reports.
- API Gateway is stateless and horizontally scalable.
Performance:
- Keep request validation lightweight.
- Avoid synchronous calls to slow downstream services.
- Use persistent connections for active traders.
Availability:
- Deploy across multiple availability zones.
- Use health checks and automatic failover.
- Keep order and market data gateways separate to isolate failures.
3. Rate Limiter
Rate limits protect the platform from abusive clients, accidental loops, and overload.
Examples:
- Per user:
100 orders/sec. - Per account:
1,000 orders/sec. - Per IP:
configurable. - Per symbol: throttle excessive cancels or replacements.
Implementation:
- Token bucket or leaky bucket.
- Redis or in-memory local limiter with periodic global reconciliation.
- For the trading hot path, prefer local in-memory rate limiting to reduce latency.
- Enforce stricter limits at the gateway and finer-grained limits near the order router.
Edge case: rate limit exceeded
{
"error": "RATE_LIMIT_EXCEEDED",
"retryAfterMs": 250
}
Important behavior:
- Do not enqueue unlimited requests.
- Fail fast.
- Return
429. - Include retry guidance.
- Track repeated violations for abuse detection.
4. Idempotency Service
Order APIs must be idempotent because clients may retry after network timeouts.
Idempotency key:
(accountId, clientOrderId, idempotencyKey)
Behavior:
| Scenario Expected Behavior |
| Same key, same payload | Return original response |
| Same key, different payload | Return 409 CONFLICT |
| Timeout after accepted order | Retry returns accepted order |
| Duplicate cancel request | Return final known cancel state |
Implementation:
- Store request hash and response for a bounded TTL.
- For accepted orders, also persist mapping from
clientOrderId to orderId. - Use strongly consistent storage for the idempotency record on the order hot path.
- Write idempotency record before publishing downstream order event.
5. Pre-Trade Risk Engine
Responsibilities:
- Margin checks.
- Buying power checks.
- Position limits.
- Exposure limits.
- Restricted instrument checks.
- Options-specific checks.
- Stop-loss validation.
- Fat-finger checks, such as rejecting prices far away from NBBO.
Data needed:
- Account balance.
- Current positions.
- Open orders.
- Latest market prices.
- Margin rules.
- Instrument metadata.
Performance design:
- Keep a hot in-memory risk state per account.
- Update risk state from executions and market data.
- Use atomic reservation when accepting an order.
- Release reservation on cancel, reject, or expiry.
- Adjust reservation on partial fills.
Example:
AvailableBuyingPower = Cash + MarginCapacity - ReservedForOpenOrders
Risk check flow:
- Validate account status.
- Validate instrument tradability.
- Estimate worst-case notional exposure.
- Check margin/buying power.
- Reserve required buying power.
- Accept or reject order.
Failure behavior:
- If risk engine is unavailable, reject new risky orders or route to degraded mode depending on regulatory requirements.
- Never accept orders without risk checks.
- Risk state must be reconstructable from ledger plus open order events.
6. Order Router
Responsibilities:
- Route orders to the correct matching partition.
- Route external orders to external venues if this is a broker model.
- Ensure each instrument maps to one primary matching engine partition.
- Preserve order sequence per instrument.
Partition strategy:
partitionId = hash(symbol) % numberOfPartitions
Better production strategy:
- Static symbol-to-partition mapping for predictable ownership.
- Rebalance cold symbols more frequently.
- Avoid moving hot symbols during trading hours.
- Keep hot symbols like
AAPL, TSLA, NVDA, SPY isolated.
Ordering guarantee:
- All orders for a given symbol must be processed sequentially by the same matching engine leader.
- This ensures deterministic price-time priority.
7. Matching Engine
The matching engine is the core low-latency stateful service.
Responsibilities:
- Maintain in-memory order books.
- Match buy and sell orders.
- Apply price-time priority.
- Generate fills.
- Persist order events.
- Publish execution reports.
Data structure:
BuyBook:
price levels sorted descending
each price level has FIFO queue of orders
SellBook:
price levels sorted ascending
each price level has FIFO queue of orders
Matching rules:
- Market buy matches lowest ask.
- Market sell matches highest bid.
- Limit buy matches while best ask <= limit price.
- Limit sell matches while best bid >= limit price.
- Stop-loss becomes active when trigger price is reached.
Durability flow:
- Receive risk-approved order.
- Assign monotonically increasing sequence number.
- Append order event to durable log.
- Apply order to in-memory book.
- Match against opposite side.
- Append execution events.
- Publish execution reports.
Why event log first?
- Prevents accepted orders from being lost.
- Enables deterministic replay.
- Enables audit and compliance.
Latency optimization:
- Keep matching engine single-threaded per partition to avoid locks.
- Use memory-resident order book.
- Use binary protocol internally.
- Use preallocated objects where needed.
- Avoid cross-partition transactions in hot path.
8. Market Data Processing
Sources:
- Exchanges.
- Market data vendors.
- Internal matching engine.
- Corporate action feeds.
- News/event feeds.
Pipeline:
- Ingest raw market data.
- Normalize into internal schema.
- Sequence events.
- Deduplicate vendor retransmissions.
- Update latest quote cache.
- Publish to WebSocket fanout.
- Store historical data.
Important guarantees:
- Use sequence numbers per symbol/feed.
- Detect gaps.
- Backfill from source if a gap is found.
- Do not silently publish out-of-order quotes.
Storage:
- Hot latest quote: Redis, Aerospike, or in-memory replicated cache.
- Historical ticks: time-series database or object storage.
- Aggregated candles: OLAP store.
9. Stop-Loss Handling
Stop-loss orders should not be treated as active market orders until triggered.
Design:
- Store stop-loss orders in a trigger book.
- Subscribe trigger engine to market data.
- When trigger condition is met:
- Convert stop-loss to market or limit order.
- Run risk check again if required.
- Submit to order router with original order lineage.
Example:
Sell stop-loss triggers when lastTradePrice <= stopPrice.
Buy stop-loss triggers when lastTradePrice >= stopPrice.
Edge cases:
- Market gaps below stop price.
- Trigger storm during volatile periods.
- Duplicate trigger events.
- Stale market data.
Mitigation:
- Use idempotent trigger IDs.
- Use sequence numbers from market data.
- Apply per-symbol trigger batching.
- Reject or pause triggering if market data is stale.
10. Execution Report Publisher
Responsibilities:
- Publish order accepted/rejected events.
- Publish partial fill and fill events.
- Publish cancellation confirmations.
- Publish trade IDs.
- Deliver events to clients in order.
Delivery semantics:
- Internally: at-least-once with idempotent consumers.
- Client-visible: sequence-numbered stream.
- Client deduplicates by
executionId.
Each report should contain:
{
"accountId": "acct_123",
"orderId": "ord_789",
"clientOrderId": "client_ord_abc",
"executionId": "exec_456",
"sequence": 982734,
"status": "PARTIALLY_FILLED",
"fillQuantity": 40,
"fillPrice": "180.21"
}
11. Notification Service
Notifications are not on the critical trading path.
Types:
- Order status notification.
- Price alert.
- Risk alert.
- Periodic daily summary.
Design:
- Consume events from Kafka/Pulsar.
- Store notification preferences.
- Fan out via:
- WebSocket.
- Push.
- Email.
- SMS.
Reliability:
- Use retry queues.
- Use dead-letter queues.
- Deduplicate by notification event ID.
- Avoid blocking trading if notification delivery fails.
12. Compliance and Audit
Compliance must be designed from day one.
Events to retain:
- Order submissions.
- Order amendments.
- Cancellations.
- Risk decisions.
- Execution reports.
- Market data snapshots used for decisions.
- User login/session metadata.
- Administrative changes.
Design:
- Immutable append-only audit log.
- Write-once storage for regulatory retention.
- Surveillance jobs detect:
- Spoofing.
- Wash trading.
- Layering.
- Excessive cancellations.
- Insider/restricted-list violations.
Replay:
- Given an
orderId, reconstruct:- Original request.
- Risk decision.
- order book state at matching time.
- execution reports.
- notifications sent.
13. Persistence Model
Use multiple stores because trading workloads are different from analytics workloads.
| Store Purpose |
| Append-only event log | Source of truth for orders and executions |
| In-memory order book | Low-latency matching |
| Snapshot store | Fast recovery |
| Relational ledger | Trades, balances, positions |
| Time-series store | Historical market data |
| Object storage | Long-term compliance archive |
| Redis/Aerospike | Latest quotes, sessions, ephemeral state |
| OLAP warehouse | Analytics and reporting |
Important principle:
The append-only event log is the source of truth.
Read models can be rebuilt.
14. Scalability Strategy
- Partition by symbol
- Each symbol belongs to one matching partition.
- Hot symbols can be isolated.
- Separate reads from writes
- Trading path optimized for correctness and low latency.
- Market data fanout optimized for high throughput.
- Use event-driven architecture
- Matching emits events.
- Notifications, compliance, analytics, and reporting consume asynchronously.
- Use backpressure
- Gateways shed load.
- Market data fanout drops or conflates stale updates for slow clients.
- Critical execution reports are never dropped.
- Scale WebSocket fanout horizontally
- Partition subscriptions by symbol.
- Use regional edge fanout.
- Use conflation for high-frequency quote updates.
15. Thundering Herd Handling
A thundering herd can happen when:
- Market opens.
- A popular stock has breaking news.
- Many clients reconnect after outage.
- Stop-loss orders trigger simultaneously.
- A price alert fires for millions of users.
Mitigations:
- Connection jitter
- Randomize client reconnect backoff.
- Queue admission control
- Reject or shed non-critical traffic early.
- Preserve trading and execution-report paths.
- Market data conflation
- For slow clients, send latest price every
100-250 ms instead of every tick. - Do not queue infinite stale updates.
- Alert batching
- Batch price alerts.
- Collapse duplicate alerts.
- Use priority queues.
- Hot-symbol isolation
- Move hot symbols to dedicated matching partitions.
- Pre-scale fanout workers before market open.
- Circuit breakers
- Pause non-essential APIs.
- Temporarily disable expensive historical queries during extreme volatility.
16. Fault Tolerance and Recovery
Matching engine recovery:
- Load latest snapshot.
- Replay append-only events after snapshot offset.
- Rebuild order book.
- Verify sequence number.
- Resume as leader.
Hot standby:
- Standby consumes the same event log.
- Maintains near-current in-memory state.
- On leader failure, standby takes over after fencing the old leader.
Fencing:
- Use lease or consensus mechanism.
- Only one matching leader per partition can accept orders.
- Prevent split-brain matching.
Data loss prevention:
- Write accepted orders to durable quorum before acknowledgement.
- Use idempotency keys to handle retries.
- Use execution IDs to deduplicate repeated reports.
17. Resilience and Degraded Modes
Possible failures:
| Failure Response |
| Market data vendor outage | Fail over to secondary vendor |
| Latest quote cache down | Use local cache briefly, then reject risk-sensitive orders |
| Risk engine down | Reject new orders or allow only risk-reducing orders |
| Notification service down | Continue trading, retry notifications asynchronously |
| Compliance consumer lag | Continue trading but alert operators |
| Matching leader down | Promote hot standby |
| Database read replica down | Route reads to another replica |
Risk-sensitive degraded mode:
- Allow order cancellations.
- Allow position-reducing orders.
- Reject new exposure-increasing orders.
- Continue sending execution reports.
18. Performance Metrics
Track these metrics continuously:
| Area Metric Target Example |
| Order Gateway | Order submit p99 latency | < 20 ms |
| Risk Engine | Risk check p99 latency | < 5 ms |
| Matching Engine | Match p99 latency | < 1-5 ms |
| Market Data | Fanout p99 latency | < 100 ms |
| WebSocket | Active connections | millions globally |
| Event Log | Append latency p99 | < 10 ms |
| Availability | Trading API uptime | 99.9%+ |
| Reliability | Lost accepted orders | 0 |
| Correctness | Duplicate executions | 0 |
| Recovery | RTO per partition | < 30 sec |
| Recovery | RPO | 0 accepted orders |
| Compliance | Audit event completeness | 100% |
| Backpressure | Dropped non-critical updates | tracked |
| Rate Limit | 429 rate by user/account | tracked |
19. Security
Key controls:
- OAuth2/OIDC authentication.
- mTLS for internal services.
- Fine-grained authorization per account.
- Signed order requests for institutional APIs.
- Encryption in transit and at rest.
- Secrets managed by KMS.
- PII isolation.
- Tamper-evident audit logs.
- Admin actions require approval and full audit trail.
20. Key Edge Cases
Edge Case 1: Duplicate Order Submission
Problem:
- Client submits an order.
- Server accepts it.
- Network times out before client receives response.
- Client retries.
Solution:
- Require
Idempotency-Key. - Store request hash and response.
- Return the original
orderId. - Reject same key with different payload.
Edge Case 2: Rate Limit Breach
Problem:
- A trading bot enters a bug loop and sends thousands of orders per second.
Solution:
- Gateway token bucket rejects excessive requests.
- Return
429. - Preserve capacity for other traders.
- Escalate suspicious behavior to abuse/risk systems.
Edge Case 3: Thundering Herd at Market Open
Problem:
- Millions of clients reconnect and subscribe to popular symbols.
Solution:
- Use jittered reconnects.
- Pre-warm market data fanout.
- Use quote conflation.
- Prioritize execution reports over quote updates.
- Apply per-client and per-symbol subscription limits.
Edge Case 4: Partial Fill Followed by Cancel
Problem:
- User cancels an order while the matching engine is partially filling it.
Solution:
- Matching engine is single-threaded per symbol partition.
- Events are processed in sequence.
- If fill event comes first, cancel applies only to remaining quantity.
- If cancel comes first, no further fills happen.
Edge Case 5: Market Data Gap
Problem:
- Market data feed misses sequence numbers.
Solution:
- Detect gap using feed sequence numbers.
- Pause publishing affected symbol if needed.
- Request replay from vendor.
- Mark quote as stale.
- Risk engine rejects orders dependent on stale data.
Final Architecture Summary
This design uses a partitioned, event-sourced, low-latency trading architecture.
The most important decisions are:
- Keep the matching engine stateful, deterministic, and single-threaded per symbol partition.
- Put risk checks before order acceptance.
- Persist every accepted order and execution to an append-only event log.
- Use idempotency keys for retry-safe order APIs.
- Separate the trading hot path from market data fanout, notifications, analytics, and compliance.
- Use snapshots plus replay for fast recovery.
- Handle overload with rate limiting, backpressure, conflation, and circuit breakers.
This gives the platform strong correctness guarantees while still supporting low latency, high throughput, resilience, scalability, and regulatory auditability.