Skip to main content

SmartBets Order Book Service

Global Architecture & Design Specification

Version: 2.0 (Revamped) Date: December 2025 Status: Canonical Reference


Table of Contents

PartTitleDescription
IExecutive SummaryWhat this is, key metrics, scope
IIBusiness ContextBetting exchanges, BACK/LAY explained
IIIThe PhilosophyDesign principles, why we made these choices
IVSystem ArchitectureRequirements, constraints, the pipeline
VData Structures Deep DiveMemory layout, BTreeMap, HashMap
VIMatching Mechanics & APIAlgorithm, order lifecycle, gRPC API
VIIDurability & Recoveryfsync barrier, crash recovery, deployment
VIIIPerformance EngineeringJournal format, TIF options, sharding
IXOperations & DeploymentMarket lifecycle, monitoring
XSecuritySecurity model, what we do/don't do
XITesting StrategyTest pyramid, critical scenarios
XIIBalance ManagementHow Backend manages funds
XIIIReferences & ResourcesPapers, videos, books
XIVFAQCommon questions answered
XVGlossaryTerm definitions

Part I: Executive Summary

What Is This Document?

This is the canonical architecture specification for the SmartBets Order Book Service - a high-performance, fault-tolerant matching engine for a betting exchange. If you need to understand how orders are matched, how data flows, or how we achieve zero trade loss, this is your source of truth.

The One-Paragraph Summary

The Order Book Service is a Rust-based matching engine that accepts orders via gRPC, sequences them with a monotonic counter, persists them to an append-only journal, matches them in a single-threaded engine, and streams results back to clients. It is inspired by the LMAX Disruptor architecture used by the London Multi-Asset Exchange.

Key Metrics At A Glance

Diagram Explanation:

This mind map shows the three pillars of the Order Book Service:

PillarWhat It MeansWhy It Matters
PerformanceFast and consistentUsers expect instant order confirmation
ReliabilityNo data loss, everFinancial system - can't lose trades
SimplicityEasy to reason aboutFewer bugs, easier debugging

What This Service Does (And Doesn't Do)

The Key Insight: The Order Book is a pure matching engine. It trusts that the SmartBets Backend has already verified the user, checked their balance, and authorized the order. This separation of concerns is what allows the Order Book to be blazingly fast.


Part II: Business Context

What Is A Betting Exchange?

A betting exchange is fundamentally different from a traditional bookmaker:

Diagram Explanation:

ModelHow It WorksWho Takes Risk
Traditional BookmakerYou bet against the house. House sets odds.The bookmaker
Betting ExchangeYou bet against other users. Exchange matches you.Other users

Why Exchanges Are Better:

  • Better Odds: No bookmaker margin baked in
  • Two-Way Market: Can bet FOR or AGAINST outcomes
  • Transparent Liquidity: See all available bets before placing yours

BACK vs LAY: The Two Sides of Every Bet

This is the most important concept to understand:

Diagram Explanation:

SideYou're BettingYour RiskYour Reward
BACKFOR the outcomeYour stake ($100)Stake × (Odds - 1) = $100
LAYAGAINST the outcomeLiability = Stake × (Odds - 1) = $100The backer's stake ($100)

Real-World Example:

ScenarioUser A (BACK)User B (LAY)
Man Utd WINS+$100 profit-$100 loss
Man Utd LOSES-$100 loss+$100 profit

The Insight: For every BACK bet, someone must be willing to LAY. The exchange's job is to match these two parties at a mutually agreeable price.

How SmartBets Uses The Order Book

Diagram Explanation:

This sequence shows the complete journey of a bet:

StepComponentWhat HappensIf It Fails
1-2Frontend → BackendUser intent capturedShow error UI
3-5BackendAuth + Balance checkReject with "Insufficient funds"
6-8Order BookMatching magicRetry or timeout
9-11BackendRecord & notifyEventual consistency

Critical Point: The Order Book (step 6-8) is the fastest part. Most latency is in steps 3-5 (database) and 9-10 (blockchain).


Part III: The Philosophy

The Core Objective

The SmartBets Order Book Service is designed with a single, uncompromising goal: Deterministic Performance.

In the world of betting exchanges, "fast" is not enough. The system must be fast consistently. A 50ms trade execution is useless if the next one takes 500ms due to a Garbage Collection pause or a database lock.

Our Guarantees:

MetricTargetWhy It Matters
Latency P99< 50msUsers expect instant response
Throughput10,000 orders/secHandle peak load
Durability0% trade lossFinancial regulation
Recovery< 2 secondsMinimize downtime

The Great Design Filter

Every architectural decision was passed through a specific filter: "Does this introduce non-determinism?"

The Design Decisions Explained:

Standard ApproachWhy We Rejected ItOur "LMAX" Approach
Microservices MeshNetwork jitter makes ordering impossibleMonolithic Logic Core: One sequence, one truth
Relational DB (SQL)Locks and buffer pools cause latency spikesIn-Memory State: All data in RAM
Multi-ThreadingContext switches and mutex contentionSingle-Threaded Core: One CPU, one thread
Floating Point0.1 + 0.2 != 0.3 breaks financial mathIntegers (Basis Points): $100.00 = 1000000

Part IV: System Architecture

Requirements & Constraints

Before diving into the architecture, let's establish what we're building for:

Functional Requirements

IDRequirementPriority
FR-1Accept BACK and LAY orders for any marketMust Have
FR-2Match orders using Price-Time PriorityMust Have
FR-3Support order cancellationMust Have
FR-4Emit trade events in real-timeMust Have
FR-5Recover from crashes without data lossMust Have
FR-6Support market lifecycle (create, open, suspend, close)Must Have
FR-7Provide order book snapshots on demandShould Have
FR-8Support multiple Time-In-Force options (GTC, IOC, FOK)Should Have

Non-Functional Requirements

IDRequirementTargetRationale
NFR-1Throughput10,000 orders/secPeak load during major events
NFR-2P99 Latency< 50msUser experience
NFR-3Recovery Time< 2 secondsMinimize downtime
NFR-4Durability0% trade lossFinancial regulation
NFR-5Memory< 500MB for 3M ordersCost efficiency
NFR-6Availability99.9% (8.7 hours/year downtime)Business requirement

Assumptions

AssumptionImplication
SmartBets Backend validates user authenticationOrder Book doesn't need auth logic
SmartBets Backend checks user balancesOrder Book doesn't need balance logic
Orders arrive via gRPC from trusted internal networkNo need for rate limiting at Order Book level
Single datacenter deployment initiallyNo cross-region replication needed
Markets are independent (no cross-market orders)Enables future sharding

Constraints

ConstraintReason
Single-threaded matching engineDeterminism requirement
Rust programming languagePerformance + safety
Kubernetes deploymentInfrastructure standardization
NVMe storage for journalLatency requirement

System Context

The Order Book is a "Dark Service". It does not speak to the outside world. It sits behind the SmartBets Backend, accepting a stream of commands and emitting a stream of facts.

Diagram Explanation:

This System Context diagram shows the Order Book's position in the architecture:

ComponentRoleWhy It Matters
UserEnd customer placing betsNever touches Order Book directly
SmartBets BackendAuthentication, validation, balance checksThe "gatekeeper" that protects Order Book
gRPC GatewayProtocol translation, connection managementHandles network complexity
The PipelineSequencing → Journal → Matching → PublishingThe deterministic core

Key Insight: The Order Book is intentionally isolated. It doesn't know about users, balances, or the outside world. It only understands: "Here's an order. Match it."


The "Pipe" Design

The system is modeled as a unidirectional pipeline of events. Data flows in one direction, is transformed, sequenced, persisted, and executed.

Diagram Explanation:

This is the heart of the architecture - "The Pipe". Every order flows through this exact sequence:

StageComponentWhat HappensFailure Mode
1gRPC ServerDecode request, validate structureReturns error immediately
2SequencerAssign sequence number (e.g., 1000001)Blocks until available
3Event JournalWrite to disk, call fsync()Order "never existed"
4Matching EngineExecute matching algorithmN/A (deterministic)
5Event PublisherStream results to clientsClient reconnects

Why "The Durability Barrier" is Orange: This is the critical safety zone. The order is NOT acknowledged until it crosses this barrier. If we crash inside it, the order is lost BUT the user knows it failed. Consistency preserved.

Why "Matching Engine" is Purple: This is the single-threaded core. No locks, no contention, no surprises. Pure deterministic execution.


Component Deep Dive

1. The gRPC Gateway (The Doorman)

Role: Validation & Translation.

ResponsibilityDetails
Connection ManagementHandles thousands of TCP connections via Tokio async runtime
Protocol DecodingDeserializes Protocol Buffer messages
Structural ValidationRejects malformed requests (negative prices, missing fields)
Threading ModelMulti-threaded worker pool absorbs network concurrency

2. The Sequencer (The Ticket Taker)

Role: Total Ordering.

The ProblemThe Solution
Two orders arrive at the "same" nanosecondSequencer assigns strict ordering
Distributed clocks disagree on timeSingle sequence number is the truth
Replay must be deterministicSequence guarantees identical replay

The Law: If Order A gets Seq: 100 and Order B gets Seq: 101, then Order A happened before Order B. Period. This is the source of truth for the entire universe.

3. The Event Journal (The Black Box)

Role: Durability & Replay.

PrincipleImplementation
Append-OnlyNever modify or delete entries
Write-AheadWritten BEFORE processing
Durablefsync() before acknowledgment

The Guarantee: We do not send Ack: OK to the user until fsync() returns success.

4. The Matching Engine (The Brain)

Role: Execution.

AspectChoiceRationale
ThreadingSingle-ThreadedNo locks = no stalls
StateIn-Memory (HashMap/BTreeMap)Microsecond access
DesignEvent-drivenDeterministic replay

5. The Event Publisher (The Broadcaster)

Role: Dissemination.

FeatureBehavior
DecouplingFast engine, slow network - never blocks
BackpressureSlow clients are DROPPED, not waited for
Fan-outOne trade → many subscribers

Part V: Data Structures Deep Dive

1. The Memory Landscape

The Matching Engine holds the entire "Known Universe" in RAM. This ensures O(1) or O(log N) access times for every operation.

Diagram Explanation:

This diagram shows how data is organized in memory for maximum performance:

Data StructurePurposeAccess Time
HashMap: MarketID → MarketFind any market instantlyO(1)
HashMap: OrderID → PointerCancel any order instantlyO(1)
BTree: Price → PriceLevelFind best price, iterate in orderO(log N)
Queue: Orders at same priceTime priority (FIFO)O(1)

Why This Structure?

OperationHow It WorksSpeed
Find market "ABC"Hash lookup in Markets map~50 nanoseconds
Find best BACK priceFirst element of BTree~10 nanoseconds
Cancel order XYZHash lookup → pointer → remove~100 nanoseconds
Add order at price 2.50BTree insert + queue append~200 nanoseconds

Why BTreeMap (not HashMap) for Prices?

ReasonExplanation
Sorted KeysAlways need "best price" (first/last item)
Range Queries"Top 5 price levels" is trivial
Cache LocalityB-Tree nodes are contiguous in memory

2. The Matching Logic (The Algorithm)

The engine runs a Price-Time Priority algorithm.

The Golden Rule:

A match occurs if Best_BACK_Price >= Best_LAY_Price.

Diagram Explanation:

This flowchart shows the matching algorithm for an incoming BACK order:

StepWhat HappensExample
1. CheckCompare incoming BACK price vs best LAY priceBACK 2.00 vs LAY 1.95
2. MatchIf BACK >= LAY, execute trade at LAY priceTrade at 1.95 (better for backer!)
3. RepeatIf quantity remains, check next LAY levelContinue until filled or no match
4. RestIf no match, add to BACK bookWait for future LAY orders

Scenario Examples:

ScenarioBACK OrderLAY Book BestResult
Match2.00 for $1001.95 for $100Trade at 1.95
Partial2.00 for $1001.95 for $50Trade $50, rest $50
No Match1.90 for $1002.00 for $100BACK rests at 1.90

3. Order Lifecycle State Machine

Diagram Explanation:

Every order goes through this state machine. Understanding it is critical for integration:

StateMeaningWhat Happens Next
PENDINGJust arrived, being processedTransitions to OPEN, PARTIAL, FILLED, or REJECTED
OPENResting in book, waiting for matchCan be matched, filled, or cancelled
PARTIALSome quantity matched, some restingCan be matched more, filled, or cancelled
FILLED100% of quantity matchedTerminal state - order complete
CANCELLEDUser cancelled or market closedTerminal state - remaining quantity gone
REJECTEDFailed validationTerminal state - never entered book

Common Transitions:

FromToTrigger
PENDING → OPENOrder added to bookNo matching counterparty
PENDING → FILLEDInstant matchCounterparty available
OPEN → PARTIALSomeone matched partNew order arrived
PARTIAL → CANCELLEDUser cancelledCancel request received

Part VI: Matching Mechanics & API Reference

1. The Contract (gRPC API)

This is the strict contract between the Backend and the Order Book.

Diagram Explanation:

The API is divided into three categories:

CategoryTypeUse Case
CommandsUnary RPC (request/response)Change state: create markets, submit orders
QueriesUnary RPC (request/response)Read state: get order book snapshot
StreamsServer Streaming RPCReal-time updates: trades, order book changes

Key Messages:

MessageFieldsNotes
SubmitOrderRequestmarket_id, user_id, client_order_id, side, price, quantityPrice in basis points (2.00 = 20000)
Eventsequence, timestamp_ns, payloadSequence is the global truth

2. Error Codes (The "No" List)

CodeMeaningSolution
MARKET_NOT_FOUNDMarket ID does not exist.Create market first.
MARKET_SUSPENDEDMarket is paused (VAR check, etc).Wait for RESUME.
INVALID_PRICEPrice is not on the valid tick grid.Round to nearest valid tick.
SELF_TRADEYou matched with your own order.Incoming order is rejected to prevent wash trading.
OVERLOADEDSystem backlog > 5000.Back off. Retry with exponential delay.

3. Performance Targets (The Promise)

MetricTargetNotes
Throughput10,000 orders/sec sustainedIncludes journal writes
P99 Latency< 50msEnd-to-end including fsync
Recovery Time< 2 secondsReplay 1M events
Memory footprint< 500MBFor 3M active orders

Part VII: Durability & Recovery

1. Durability (The "fsync" Barrier)

We are a financial system. Data loss is existential.

The Guarantee

"If we told you we took your order, we have it on disk."

This is achieved via the fsync() barrier in the Sequencer.

Diagram Explanation:

This sequence diagram shows the critical durability guarantee:

PhaseWhat HappensIf Crash Here
Before Danger ZoneRequest received, not yet writtenOrder lost, user gets timeout, retries
Inside Danger ZoneWriting to disk, waiting for fsyncOrder lost, user gets timeout, retries
After Danger Zonefsync complete, ACK sentOrder survives, replayed on restart

The Key Insight: We NEVER acknowledge an order until it's durable on disk. This is why the "Danger Zone" is highlighted - if power fails there, the user's request times out and they retry. No inconsistency.


2. Crash Recovery (The Time Machine)

When the service restarts (after a crash or deploy), memory is empty. It must rebuild the universe from the journal.

Diagram Explanation:

This flowchart shows how the system recovers after any restart:

StepWhat HappensTime
1. Check SnapshotLook for saved state~10ms
2. Load SnapshotRestore engine to sequence N~100ms
3. Replay JournalApply events from N+1 to current~2ms per 1000 events
4. ReadyOpen for tradingTotal: < 2 seconds

Recovery Time Examples:

ScenarioSnapshot AgeJournal SizeRecovery Time
Clean restartFresh1,000 events< 100ms
Normal crash1 hour old50,000 events~500ms
Long outage1 day old1,000,000 events~2 seconds

3. Production Deployment (Kubernetes)

We run as a Single Pod StatefulSet.

QuestionAnswer
Why not a Deployment?Need stable disk identity
Why only 1 replica?Single writer to journal
What about HA?Fast recovery (< 2 sec) is the strategy

Diagram Explanation:

This deployment diagram shows the production infrastructure:

ComponentInstancesRole
NGINX Ingress1Load balancer for HTTP traffic
Backend Pods3SmartBets app servers (stateless, scalable)
Order Book Pod1The matching engine (stateful, single instance)
NVMe PV1Persistent volume for journal + snapshots

Why Single Instance?

ConcernSolution
"What about availability?"Fast recovery (< 2 sec)
"What about scaling?"10K TPS is plenty; shard by market if needed
"What about data loss?"Journal is durable; replicated storage optional

Configuration Specs

ResourceValueRationale
CPU2 Dedicated Cores1 for engine, 1 for Tokio/IO
RAM2GBPlenty for 10M orders
DiskNVMe SSDLow latency for fsync

4. Diagnostics & Monitoring

Diagram Explanation:

This shows the observability pipeline:

ComponentRole
Metrics EndpointExposes Prometheus format on /metrics
PrometheusScrapes every 15 seconds, stores time series
GrafanaDashboards for visualization
AlertmanagerRoutes alerts based on severity

Critical Alerts

Alert NameConditionMeaningAction
OrderBookDownup == 0Service crashedK8s restarts automatically
SlowMatchingp99_latency > 100msSomething blocking engineInvestigate thread
JournalLagwrite_latency > 100msDisk I/O chokingCheck disk health
SequenceGapseq_in != seq_out + 1CRITICAL: Determinism brokenManual investigation

Appendix: Technology Stack

ComponentTechnologyWhy
LanguageRust 1.83+Memory safety, zero-cost abstractions
Async RuntimeTokioBest-in-class async I/O
gRPCTonicNative Rust, high performance
SerializationProst (Protobuf)Fast, schema-driven
BenchmarkingCriterionStatistical rigor for perf testing

Part VIII: Performance Engineering

1. The Journal Format

The Event Journal uses a structured binary format for durability and fast recovery.

Diagram Explanation:

FieldSizePurpose
Length4 bytesTotal entry size for seeking
Checksum4 bytesCRC32 to detect corruption
Sequence8 bytesThe global ordering truth
Timestamp8 bytesNanoseconds since epoch
Type1 byteOrder, Cancel, or SnapshotMarker
PayloadVariableProtobuf-encoded event

Why This Format?

ConcernSolution
Corruption detectionCRC32 checksum on every entry
Fast seekingLength field enables skipping
Replay determinismSequence ensures ordering
Segment rotation1M events per file for manageability

2. Time-In-Force (TIF) Options

Diagram Explanation:

TIFMeaningBehavior
GTCGood Till CancelledMatch what you can, rest remainder in book
IOCImmediate Or CancelMatch what you can, cancel remainder
FOKFill Or KillAll or nothing - no partial fills

Use Cases:

Order TypeWhen To Use
GTCNormal limit orders, willing to wait
IOCWant immediate execution, don't want to rest
FOKLarge orders, need full fill or none

3. Future Scaling: Market Sharding

Current: 10,000 TPS on 1 node. Future: 100,000 TPS via sharding.

Diagram Explanation:

ComponentRole
Router ServiceConsistent hashing on market_id
Order Book NodesEach owns 1/N of all markets
JournalsEach node has independent journal

Sharding Strategy:

ApproachProsCons
Random hashEven distributionCorrelated markets on different nodes
Explicit assignmentKeep related markets togetherManual management
HybridBest of bothMore complex routing

Recommendation: Keep correlated markets (e.g., all EPL games) on same shard explicitly for accumulators.


Part IX: Operations & Deployment

Market State Machine

Diagram Explanation:

StateOrders Accepted?Matching?Use Case
CREATED❌ No❌ NoSetup phase, configuring
OPEN✅ Yes✅ YesNormal trading
SUSPENDED❌ No❌ NoPause (goal scored, VAR)
CLOSED❌ No❌ NoEvent finished

Transition Rules:

FromToTriggerWhat Happens
CREATED → OPENOpenMarketStart accepting orders
OPEN → SUSPENDEDSuspendMarketReject new orders, keep existing
SUSPENDED → OPENResumeMarketResume trading
Any → CLOSEDCloseMarketCancel all orders, final state

Part X: Security

Security Model

The Order Book operates on a "Trust the Backend" security model:

Diagram Explanation:

ZoneComponentsSecurity Level
UntrustedUsers, InternetAssume hostile
DMZWAF, Load BalancerFilter attacks
TrustedBackend, Order BookInternal network only

Security Measures

MeasureImplementationPurpose
Network IsolationOrder Book not exposed to internetReduce attack surface
mTLSMutual TLS between Backend and Order BookAuthenticate both parties
Input ValidationProtobuf schema + business rulesPrevent malformed data
Self-Trade PreventionReject orders matching own ordersPrevent wash trading
Rate LimitingAt Backend level, not Order BookPrevent DoS

What Order Book Does NOT Do

Security FunctionHandled By
User authenticationSmartBets Backend (JWT)
AuthorizationSmartBets Backend
Balance validationSmartBets Backend
Fraud detectionSmartBets Backend
Audit loggingSmartBets Backend

Part XI: Testing Strategy

Testing Pyramid

Test Categories

CategoryWhat It TestsToolsRun Time
Unit TestsIndividual functions, matching logiccargo test< 10 seconds
Integration TestsgRPC API, journal persistencecargo test --features integration< 1 minute
Property TestsInvariants (no negative balances, etc.)proptest< 5 minutes
Benchmark TestsPerformance regressioncriterion< 10 minutes
E2E TestsFull flow with BackendDocker Compose< 5 minutes

Critical Test Scenarios

ScenarioWhat We Verify
Crash RecoveryReplay journal, state matches pre-crash
Concurrent OrdersSequence numbers are unique and ordered
Self-TradeOrders from same user don't match
Price-Time PriorityEarlier orders at same price fill first
Partial FillsRemaining quantity tracked correctly
Market SuspensionOrders rejected when suspended

Determinism Testing

The Determinism Guarantee: Given the same sequence of input events, the engine MUST produce the exact same output. This is tested by replaying journals multiple times and comparing final states.


Part XII: Balance Management Flow

How SmartBets Backend Manages Balances

The Order Book does NOT manage balances. Here's how the full flow works:

Diagram Explanation:

PhaseStepsWhat Happens
Reserve2-5Backend checks balance, reserves funds
Match6-8Order Book matches, unaware of balances
Settle9-10Backend moves funds, creates position

Balance States

StateMeaningExample
AvailableCan be used for new bets$400
ReservedLocked for pending orders$100
TotalAvailable + Reserved$500

What If Order Book Crashes?

Key Insight: Because the Backend reserves funds BEFORE sending to Order Book, a crash never results in lost money. The worst case is a timeout and retry.


Part XIII: References & Resources

Foundational Reading

ResourceTypeWhy Read It
LMAX ArchitectureArticleThe inspiration for our design
The LMAX DisruptorDocumentationRing buffer pattern we adapted
Event SourcingArticleWhy we use append-only journals

Videos

VideoDurationTopic
LMAX - How to Do 100K TPS at Less Than 1ms Latency50 minOriginal LMAX presentation
The Art of the Event-Sourced Microservice45 minEvent sourcing patterns

Books

BookAuthorRelevance
Designing Data-Intensive ApplicationsMartin KleppmannChapters on event logs, stream processing
Systems PerformanceBrendan GreggUnderstanding latency, profiling
ProjectLanguageWhat To Learn
matching-engineRustSimilar architecture
disruptor-rsRustRing buffer implementation

Part XIV: Frequently Asked Questions

General

Q: Why Rust instead of Java/Go/C++?

A: Rust gives us:

  • Memory safety without garbage collection (no GC pauses)
  • Zero-cost abstractions (fast as C, safe as Java)
  • Excellent async support (Tokio)
  • Strong type system catches bugs at compile time

Q: Why single-threaded? Isn't that slow?

A: Counter-intuitively, single-threaded is FASTER for our use case:

  • No lock contention
  • No context switching
  • Perfect cache locality
  • Deterministic execution

LMAX proved this with 6 million TPS on a single thread.

Q: What happens if the Order Book crashes?

A:

  1. Kubernetes restarts the pod (< 5 seconds)
  2. Order Book replays journal (< 2 seconds)
  3. Trading resumes with exact same state
  4. No trades are lost

Q: How do you handle time zones?

A: All timestamps are UTC nanoseconds since epoch. No time zones in the Order Book.

Technical

Q: Why not use a database?

A: Databases introduce non-determinism:

  • Lock contention varies
  • Query plans change
  • Buffer pool behavior unpredictable

We use the journal as our "database" - append-only, sequential, predictable.

Q: How do you prevent duplicate orders?

A: Each order has a client_order_id provided by the Backend. The Backend is responsible for deduplication. The Order Book trusts the Backend.

Q: What's the maximum order size?

A: Technically unlimited, but the Backend enforces limits based on user tier and market liquidity.

Q: How do you handle floating point precision?

A: We don't use floating point. All prices and quantities are integers:

  • Price: Basis points (2.00 = 20000)
  • Quantity: Smallest currency unit (cents, satoshis)

Operations

Q: How do you deploy without downtime?

A: We accept brief downtime (< 5 seconds):

  1. Stop accepting new orders
  2. Drain pending orders
  3. Take snapshot
  4. Deploy new version
  5. Replay from snapshot
  6. Resume trading

Q: How do you debug production issues?

A:

  1. Metrics in Grafana show symptoms
  2. Logs in Loki show context
  3. Journal replay reproduces exact state
  4. Determinism means we can debug locally with production data

Q: What's the disaster recovery plan?

A:

  1. Journal is on durable storage (replicated)
  2. Snapshots are backed up to S3 hourly
  3. Recovery: Restore snapshot + replay journal
  4. RTO: < 30 minutes, RPO: 0 (no data loss)

Part XV: Glossary

TermDefinition
BACKA bet FOR an outcome (e.g., "Man Utd to win")
LAYA bet AGAINST an outcome (accepting a BACK bet)
Basis Points1/100th of a percent; we use 10000 = 1.00 odds
BTreeMapBalanced tree data structure, sorted keys, O(log N) operations
DeterministicSame input always produces same output
Event SourcingStoring all changes as immutable events
FOKFill Or Kill - order must fill completely or be rejected
fsyncSystem call that ensures data is written to disk
GTCGood Till Cancelled - order stays until filled or cancelled
gRPCGoogle's RPC framework using Protocol Buffers
HashMapHash table data structure, O(1) average operations
IOCImmediate Or Cancel - fill what you can, cancel rest
JournalAppend-only log of all events
LatencyTime from request to response
LMAXLondon Multi-Asset Exchange, inspiration for our architecture
mTLSMutual TLS - both client and server authenticate
NVMeFast SSD storage protocol
P9999th percentile - 99% of requests are faster than this
Price-Time PriorityBest price first, then earliest order first
ProtobufProtocol Buffers - binary serialization format
Sequence NumberMonotonically increasing ID for total ordering
SnapshotPoint-in-time copy of engine state
StatefulSetKubernetes resource for stateful applications
ThroughputNumber of operations per second
TIFTime In Force - how long an order stays active
TokioAsync runtime for Rust
TonicgRPC library for Rust

End of Specification.

Last Updated: December 2025 Maintainer: SmartBets Engineering Team