~learn.

NSE Stock Exchange, the whole design.

An exchange core for ~1 million messages a second on a record day (21.89 billion), where one sequencer and one deterministic matching thread per partition decide "first", multicast gives every subscriber each tick at once, and nothing is acknowledged until a surviving copy can replay it.

7 diagrams · 8 sections · revise in ~10 min · Download PDF prints it in the light theme, diagrams included

SQ-33 · NSE Stock Exchange · design sheethimanshukukreja.in/learn/sheets/bonus-33-nse-stock-exchange

At a glance#

Number Value What it drives
Order messages, record day 21.89 billion (24 March 2026) ~973,000 / s average over 22,500 s
Trades, record day 201 million ~109 messages per trade: size by messages
Published capacity ~5 million messages / s expiry bursts near it (est. ~4.3M / s)
Matching partitions (design) ~20, one thread each ~500k / s each (assumed), half-loaded at peak
Full tick-by-tick feed ~2 Gbit/s at peak (est.) multicast once, not TCP per subscriber
Journal ~2.2 TB / day · ~3.5 Gbit/s to near site (est.) synchronous near site, async DR
Recovery declare in 30 min · restore in 45 min after (SEBI) live DR drills, failover as one unit
Investors 129.09 million unique (31 March 2026) 1,325 members, 200,000+ terminals

Architecture#

DiagramOrder entry, one sequenced core, and everything that reads its output
%% title: Order entry, one sequenced core, and everything that reads its output
flowchart TD
  MEM@{ icon: "sd:users", label: "Members<br/>brokers' offices · co-location racks" }
  GR@{ icon: "sd:router", label: "Gateway router<br/>least-loaded gateway" }
  GW@{ icon: "sd:gateway", label: "Gateways<br/>connection rate · sliding window" }
  CHK["Checks before the book<br/>price band · freeze qty · value · status"]:::service
  SEQ["Sequencer per partition<br/>next number · journal"]:::hot
  JRN@{ icon: "sd:log", label: "Journal<br/>input log" }
  NS@{ icon: "sd:database", label: "Near site<br/>synchronous copy" }
  DR@{ icon: "sd:region", label: "DR site, Chennai<br/>asynchronous mirror" }
  ME["Matching thread<br/>in-memory books · price-time"]:::core
  MD@{ icon: "sd:network", label: "Market data<br/>multicast A and B feeds" }
  CLR["NSE Clearing<br/>novation · real-time margins"]:::core
  SURV@{ icon: "sd:monitor", label: "Surveillance<br/>replays the log" }
  MEM ==> GR
  GR -.->|"assigns"| GW
  GW ==> CHK ==> SEQ
  SEQ ==> JRN
  SEQ ==> ME
  JRN ==> NS
  JRN -.-> DR
  ME ==> MD
  ME ==>|"trades"| CLR
  ME --> SURV
  CLR -.->|"disable member"| CHK
  class MEM client
  class GR,GW edge
  class JRN,NS store
  class DR external
  class MD queue
  class SURV service
DiagramZoom-in · one partition with output gating
%% title: Zoom-in · one partition with output gating
flowchart TD
  G1@{ icon: "sd:gateway", label: "Gateways<br/>admitted messages" }
  SEQ["Sequencer<br/>assign seq · journal"]:::hot
  ME["Matching thread<br/>applies in sequence"]:::core
  HS["Hot standby<br/>same log · same code"]:::core
  NS@{ icon: "sd:database", label: "Near site<br/>synchronous journal" }
  GATE{"Input durable on<br/>standby and near site?"}
  OUT@{ icon: "sd:stream", label: "Acks · trades · ticks<br/>released in order" }
  G1 ==> SEQ
  SEQ ==> ME
  SEQ ==> HS
  SEQ ==> NS
  ME ==> GATE
  HS -.->|"book hash every N"| GATE
  NS -.->|"ack"| GATE
  GATE ==>|"yes"| OUT
  class G1 edge
  class NS store
  class OUT queue

Key flows#

DiagramOne order from a broker's session to a trade, a tick and clearing
%% title: One order from a broker's session to a trade, a tick and clearing
sequenceDiagram
  autonumber
  participant B as Broker
  participant G as Gateway
  participant S as Sequencer
  participant M as Matching thread
  participant D as Multicast stream
  participant C as NSE Clearing
  B->>G: new order · 1 lot @ 4.20
  G->>G: rate · price band · value · member status
  G->>S: forward
  S->>S: next seq · journal to standby and near site
  S->>M: apply in sequence
  M-->>G: ack · order number = partition + sequence
  M->>M: crosses resting sell at 4.20
  M-->>G: confirmations to both members
  M->>D: tick · one packet for every subscriber
  M->>C: trade · applied once by sequence
  Note over S,M: outputs leave only after the input is durable
DiagramA session drops · replay, then act on what happened
%% title: A session drops · replay, then act on what happened
sequenceDiagram
  autonumber
  participant B as Broker
  participant R as Gateway router
  participant G as New gateway
  participant L as Output log
  B->>R: logon after drop
  R-->>B: new gateway · session key
  B->>G: download stream 7 from last seq
  G->>L: this trader's messages after that seq
  L-->>B: ACK new order · TRADE on older order
  B->>G: modify older order · last activity reference
  alt reference matches
    G-->>B: modified
  else order changed since
    G-->>B: rejected · stale version, re-read
  end
  Note over B,G: ask, don't resend
DiagramCritical systems fail · halt, declare, fail over as one unit
%% title: Critical systems fail · halt, declare, fail over as one unit
sequenceDiagram
  autonumber
  participant O as Operations
  participant P as Primary site
  participant D as DR site
  participant M as Members
  P-->>O: risk, index, surveillance down · trading healthy
  O->>P: halt all segments
  O->>M: trading halted
  Note over O: declare within 30 min · restore within 45 min
  O->>D: activate trading, risk, clearing, index, surveillance
  D->>D: replay journals to last replicated seq
  M->>D: logon via router · download messages
  Note over D,M: multicast streams restart at seq 1
  D->>M: pre-open call auction, then continuous trading

Data model#

DiagramCore entities
%% title: Core entities
classDiagram
  class Partition {
    +partitionId : int
    +epoch : int · fences a deposed sequencer
    +lastSeq : long
    +contracts : list
  }
  class Book {
    +contract : token
    +bids : price levels · FIFO queues
    +asks : price levels · FIFO queues
  }
  class Order {
    +orderNo : partition and sequence
    +side : BUY or SELL
    +price : int · in ticks
    +qty : int
    +lastActivityRef : long · version for modify
    +clientCode : string
    +algoId : int · if algorithmic
  }
  class Session {
    +connectionId : int
    +subscribedRate : msgs per second
    +lastSeqSeen : long per stream
  }
  class Trade {
    +partition : int
    +seq : long · unique with partition
    +buyOrder : orderNo
    +sellOrder : orderNo
    +qty : int
    +price : int · in ticks
  }
  Partition "1" --> "many" Book : owns
  Book "1" --> "many" Order : queues
  Session "1" --> "many" Order : sends
  Order "1" --> "many" Trade : fills in

Lifecycle#

DiagramAn order, from entry to done
%% title: An order, from entry to done
stateDiagram-v2
  [*] --> CHECKED: gateway admits it
  CHECKED --> REJECTED: rate, band or limit fails
  CHECKED --> SEQUENCED: sequencer numbers it
  SEQUENCED --> OPEN: rests in the book
  SEQUENCED --> FILLED: crosses fully
  OPEN --> OPEN: modify with current reference
  OPEN --> PART_FILLED: trades in part
  PART_FILLED --> FILLED: rest trades
  OPEN --> CANCELLED: cancel or close
  PART_FILLED --> CANCELLED: cancel or close
  FILLED --> [*]
  CANCELLED --> [*]
  REJECTED --> [*]
  class FILLED ok
  class REJECTED bad
  class PART_FILLED queue

Decisions#

Decision Chose Over Because
Who decides first Sequence number Gateway clocks clocks drift and tie
Concurrency One thread per partition Locks on a book lock order can't be replayed
Time Sequenced events Reading the clock replay must match
Durability Output gating, sync near site Async replication nothing acked is lost
Margin Status bit from clearing Inline check per order gateway checks stay local
Market data Multicast, A/B, recovery TCP per subscriber equal by construction
Pre-open close Random in 8th minute Fixed instant no prize for being last

When it breaks#

Failure What users see Contain it with
Runaway member algo its own rejects, then disconnect connection rate · cut at 2× · kill switch
Primary engine dies brief pause, same book gated outputs · hash-checked standby · epoch
Session drops mid-burst unknown order state message download by sequence
Multicast packet loss nothing, usually feed B · rate-limited TCP recovery
Risk or index system down market halted halt · declare in 30 min · DR as one unit
Near-site link degrades slower acks shed traffic · stay synchronous · halt if lost

Say it in the interview#