fivenines
11/39
Lesson 1.8

Market data at scale

What you'll learn

Why market data is the exchange's hardest scaling problem (not matching), and the two tools that tame it: tiered feeds and conflation.

Building on

Every match in 1.3 emitted public updates. Multiply by 10 million users and see what happens.

Run the numbers. The core produces perhaps 500k book updates/second at peak. Matching handles that in one process. But market data must deliver those updates to every subscriber: 500k updates × 200k concurrent subscribers is 1011 messages per second of naive fan-out. The bottleneck of an exchange at scale is not deciding trades — it's telling everyone about them.

Tool 1 — tiered feeds. Different consumers need radically different fidelity, so we sell different products:

TierContentVolumeConsumer
L1Best bid/ask + last tradeTinyRetail apps, tickers — the vast majority of users
L2Aggregated depth, top 10–20 price levelsModerateActive traders, charting tools
L3Every individual order event, add/modify/cancelFull firehoseMarket makers, HFT — a few hundred firms
DelayedAny of the above, 15 minutes lateFree tiers, websites

Tool 2 — conflation. A phone on hotel Wi-Fi cannot drink from even the L1 firehose during a volatile minute. Rather than queue unboundedly (memory death) or disconnect the client (availability death), the feed server conflates: it keeps only the latest state per symbol, and when the slow client is ready, sends current truth — skipping the intermediate churn the client no longer cares about.

flowchart TB
    ME["Matching engine"] --> MDP["Publisher: builds L1 / L2 / L3 streams"]
    MDP --> F1["Feed servers — L3 firehose"]
    MDP --> F2["Feed servers — L1/L2 fan-out tier"]
    MDP --> DLY["Delay buffer — 15 min"]
    F1 --> MM["Hundreds of firms — every message, gap-detected"]
    F2 --> FAST["Fast consumers — every update"]
    F2 --> SLOW["Slow consumers — conflated: latest state per symbol"]
    DLY --> FREE["Millions of free-tier users via CDN-style edge caches"]
    
Fan-out as a tree. Each layer multiplies reach; conflation at the leaves converts "can't keep up" from a failure into a quality-of-service level. Slow consumers get correct-but-sparser truth, never a stale queue or a dropped session.

Conflation works because L1/L2 data is state, not history — a client showing prices needs the current best bid, not every bid that briefly existed. L3 consumers, who genuinely need history, get sequence-numbered streams with gap detection instead (the mechanics arrive in lesson 2.3). Note the asymmetry with private data: your own fills are never conflated. Public state can be summarized; personal facts cannot.

Key ideas
  • Fan-out, not matching, is the scale bottleneck: messages × subscribers.
  • Tier the product: L1/L2/L3/delayed serve different needs at different volumes.
  • Conflate public state for slow consumers; never conflate private facts.
Next step

See what actually stuck.

Take the practice scenarios now.