How Zerodha Processes 50,000 Stock Trades Per Second Without Burning Down Its Database
Imagine it is 9:15 AM on a Monday morning. Millions of traders open their stock apps at the exact same second, all hammering the "BUY" button at once. That creates a tidal wave of 50,000 requests per second hitting the system.
If you try to save every order straight to a normal database like MySQL or PostgreSQL at that speed, your database will lock up, freeze, and crash in seconds. But Zerodha - one of India's largest discount brokers, processes this morning rush smoothly. How do they validate user balances, route orders to the stock exchange, and keep financial accounts accurate without failing? Let’s break down the system design step by step.
The Core Systems Behind the Scale
To handle 50k orders per second without losing data or slowing down, Zerodha breaks the work into specialized components. Here is high level architecture for this.

Edge Layer & Validation Engine
What is it? The front door of the system. It consists of an API Gateway and light validation services.
Why do we need it? When a user taps "BUY", this layer performs fast checks in RAM before the request hits the core processing engines. It authenticates the user, checks basic price/quantity rules, and performs an Idempotency Check using Redis (like checking a unique ticket number to make sure a double-click doesn't buy the same stock twice).
What is the catch? Everything in this layer must be stored in fast RAM (in-memory cache). If your cache goes down or lags, users will see delays before their request even enters the system.
OMS & RMS Core (Order & Risk Management System)
What is it? The central brain of the trading platform. It manages the life cycle of an order and checks if you actually have enough money to make the trade.
Why do we need it? It tracks the order status through a state machine (CREATED → BLOCKED → SENT → EXECUTED) and manages user balances in real time using atomic operations (like a strict lock that deducts money safely without letting two transactions touch the same cash at once).
What is the catch? Keeping user balances in RAM makes operations fast, but if the engine server crashes, that in-memory state is lost unless it is written to disk instantly.
Persistence Layer
No single database strategy can handle massive write operations with validations and ultra fast processing.
Zerodha uses Rocks DB. An ultra-fast key-value storage engine that runs inside the application code itself rather than over a network connection. Think of it like a notepad sitting right next to the cash register where every transaction is written down instantly on a local drive.
Why do we need it? Traditional databases slow down because requests travel over network wires. RocksDB writes data to local disk logs (Write-Ahead Logging or WAL), allowing a single server node to handle over 100,000 writes per second.
But only Rocks DB can’t be source of the truth as backend so Zerodha uses Postgres SQL as persistent store. A local background worker (or CDC / Change Data Capture like Debezium) reads from this local WAL and pushes it to Kafka. Kafka consumers write data to PostgresSql
What is the catch? Rocks DB is good for massive writes but not a replacement of traditional DB because it can’t handle complex SQL structure or schema and joins. Also it has data specific to a node and can’t find data across multiple server nodes. But now here is a catch, If user A places an order, how does the application ensure that status update from exchange lands to the correct node where user A status is stored in RocksDB? Or if the user cancels the order then it lands to the same node where RocksDB has order data of user A? It uses application level consistent hash proxy pattern
Application-Level Consistent Hash Proxy Pattern
Since Zerodha is using Rocks DB and Rocks DB is maintained as in-memory process along with your application node. So it doesn’t have any info about data from another node. So how does it make sure that all request from a user goes to same node and kafka event received from exchange is processed by same node.
For this Zerodha uses application level consistent hash proxy pattern. A smart routing rule based on math:
Hash(user_id) % total_shards. Sharding is like breaking a giant 1,000-page directory into smaller 50-page regional booklets so searching is faster.Why do we need it? It ensures that any request for user A goes to the same node(node1) every time where its local Rocks DB is running. Also any kafka event falls to the same partition, partition 0 and node1 is a dedicated listener of partition 0.
What is the catch? If a server node crashes or if you add new server nodes to the cluster, recalculating the hash assignments can temporarily route traffic awkwardly while the system rebalances.


Handling Run Time Exchange Restrictions or Rules Modifications
Imagine a scenario that during mid session, agency enforces some restrictions that needs to be applied immediately, like - can’t place more than 100 unit order on a particular stock.
Agency publishes the rules via messages and stock brokers listens to it
Conditions are updated in in-memory cache and also written to permanent storage
Whenever application crashes, application reloads info from permanent storage to in-memory cache
Consistency Between Money Debited and Order Execution
To ensure that order is not placed without debiting money or money is not debited without placing order, zerodha rely on Atomic Operations and Margin Pre-validation Architecture
Money is not debited in real time as soon as an order is placed, but the moment you tap Buy, Zerodha’s Risk Management System intercepts the request before it reaches the exchange. It verifies whether your available ledger balance + collateral meets the required margin.
If funds are available, Zerodha instantly blocks the required cash in your trading account balance. The money is not spent yet, but it cannot be used for any other trade.
The check-and-block phase is written as an atomic transaction(ACID compliant).
If the database successfully blocks the funds, the system proceeds to send the order packet to the exchange FIX gateway.
If the database write fails or timeouts occur during the lock phase the transaction rolls back, no funds are blocked, and the order is marked Rejected.
Final fund debits do not happen in real time to the banking system - they happen at end-of-day clearing via NSE Clearing Limited (NCL) or ICCL under SEBI supervision:
Every night, Zerodha reconciles its internal order logs against the exchange's trade file. Also it fixes any discrepency
What Do You Think?
If you were building a high-frequency system like this what all tech or architectural changes would you make? Reply and let me know your thoughts!
Cheers,
Tech Builder
