Zerodha System Design Interview: Real-Time Trading at Scale
On the 2024 election results day, Zerodha's market-data service streamed about 175 million price ticks per second to hundreds of thousands of connected traders, and it did so from a single Go program. Zerodha is one of India's largest retail brokers, with close to 8 million NSE active clients, run by a technology team of roughly 30 people.
Designing Zerodha is the real-time trading problem. You have to stream live market prices to hundreds of thousands of users at once with very low latency, take an order from a phone and route it to the exchange and back through an order management system, keep positions and funds correct to the paisa, and survive the enormous spike at the 9:15 market open. It is also a lesson in restraint: Zerodha runs this at national scale on a small team with few services, a Postgres-first design, and Redis holding the hot data in memory. The interview rewards both the real-time streaming design and the judgment to keep the system simple.
Asked at: Commonly asked at Zerodha, Groww, Upstox, Angel One, and fintech and trading teams, and the general form, meaning design a stock trading app or a real-time price ticker, shows up at Uber, Google, and most product companies for SDE2 and SDE3 rounds. It is the canonical real-time market-data and order-management question, popular because live streaming to hundreds of thousands of clients and a strict order lifecycle are both hard and concrete.
Why this question is asked
A trading platform forces two problems that a normal app does not. First, real-time fan-out: the price of an instrument changes many times a second, and every user watching it needs the update almost instantly, so you cannot poll a database, you have to push over persistent connections at very high volume. Second, a strict order lifecycle against a system you do not control, the exchange, where an order can be placed, partially filled, filled, rejected, or cancelled, and money and positions must always reconcile. On top of that the load is spiky in a very specific way, with a huge surge at the market open. Interviewers use Zerodha to check whether you can design a WebSocket streaming layer, reason about an order management system and exchange connectivity, decide what belongs in memory versus a database, and, just as important, whether you can resist over-engineering a system that a few well-chosen services can handle.
Requirements
Always clarify these in the first 5 minutes of the interview. Do not start drawing boxes until both lists are agreed.
Functional requirements
- User sees live prices for the instruments on their watchlist, updating in real time
- User places an order (market or limit, buy or sell), which is routed to the exchange, and sees its status change live
- Order moves through a lifecycle: placed, sent to exchange, open, fully or partially filled, rejected, or cancelled
- User sees positions, holdings, and profit and loss update as trades execute and prices move
- User sees available funds and margin, and cannot place an order beyond what risk rules allow
- Historical charts and market depth (the top bids and offers) for an instrument
- End-of-day reports such as contract notes are generated and delivered to every client
- The platform exposes an API so third-party apps and algorithms can trade and stream data
Non-functional requirements
- Live price updates pushed to hundreds of thousands of concurrent connections with very low latency
- The system must absorb the market-open surge at 9:15, when a large share of the day's users connect and act within minutes
- Orders and money must always reconcile: positions, funds, and executions can never drift, even under load or partial failure
- High availability during market hours, with redundant paths to the exchange so a single failure does not stop trading
- Read-heavy user screens (watchlist, positions, portfolio) must return in a few milliseconds
- Handle multiple millions of trades on a busy day and hundreds of millions of price ticks per second at peak
- Stay operable and cost-efficient for a small team, favoring few services over many
Back-of-envelope scale estimates
Show your math. Pulling numbers from thin air signals you have not thought about the load.
Active clients
~7.9M NSE active (FY25), #2
Zerodha had about 7.9 million NSE active clients at the end of FY25, roughly 16 percent market share, ranking second after Groww. Its own total registered client count was about 14 million as of mid-2024. Active and registered are different metrics, so keep them separate.
Peak market ticks per second
~175M ticks/s
On 4 June 2024, election results day, Zerodha's ticker served about 175 million market ticks per second to clients. This is the headline real-time number and the anchor for the streaming design.
Concurrent WebSocket connections
Hundreds of thousands
Zerodha states its ticker serves hundreds of thousands of concurrent WebSocket connections, broadcasting millions of quotes per second, from a single Go binary. This is what sizes the streaming layer.
Trades per day
8-12M on busy days
Zerodha has referenced multiple 8 to 9 million trade days, with peaks around 12 million daily trades. Divided across the roughly 6.25 hour trading day, that is a few hundred trades per second on average, with far higher bursts at the open.
Exchange connectivity
8 OMS setups, 58 servers, 44 leased lines
Zerodha reports running 8 independent order management system setups across Mumbai and a Chennai disaster-recovery site, on 58 servers, with 44 exchange leased lines to NSE, BSE, and MCX. This is the redundancy that keeps trading up.
Engineering team
~30 people
Zerodha runs this platform for millions of clients with a technology team of around 30. It is the reason the design favors few services and simple, well-understood building blocks.
High-level architecture
Split Zerodha into two worlds that meet at the order: the client-facing world and the exchange-facing world. This split is the single most important fact about the design, and Zerodha has stated it directly. The client-facing world is Kite, the trading app and its backend, which runs on the public cloud, on AWS across three availability zones in the Mumbai region. This is where users log in, load their watchlist, see positions and funds, and place orders. The screens are read-heavy, so Zerodha keeps the hot data in memory: it has said that every bit of data shown on Kite comes from a hot Redis cache, with orders, positions, and portfolio served as O(1) in-memory lookups, a few hundred gigabytes of data kept as byte blobs in Redis rather than queried from the database on every request. PostgreSQL is the durable store behind this, running as large multi-terabyte instances with hundreds of billions of rows. The services are written mostly in Go and fronted by Nginx. The real-time price stream is its own piece. Zerodha runs a ticker, a single Go binary, that holds hundreds of thousands of concurrent WebSocket connections and broadcasts millions of quotes per second, peaking around 175 million ticks per second on the busiest day. The wire format is compact and binary: prices are sent as integers in paise, and a client subscribes to instruments in one of a few modes, from a tiny last-traded-price packet up to a full packet that includes five levels of bid and offer market depth. Live ticks are not written to a database at full fidelity; they live in memory and are pushed out. The exchange-facing world is the order management system, and it does not run in the cloud. Zerodha runs its OMS on its own physical racks in colocation, close to the exchanges, connected by leased lines. It reports 8 independent OMS setups across Mumbai and a Chennai disaster-recovery site, on 58 servers, with 44 leased lines to NSE, BSE, and MCX for primary and backup paths. When a user places an order, Kite hands it to an OMS instance, which sends it to the exchange over a leased line, and the exchange responds with acknowledgements and fills that flow back and update the order, the position, and the funds. The OMS software itself, called OmneNest, is bought rather than built, while the ticker and the client backends are built in house. The design philosophy tying it together is deliberate restraint. Zerodha has written openly against microservice sprawl and service meshes added for no clear reason, and argues that most business problems are relational CRUD that a single well-indexed Postgres node handles for a very long time before distributed systems are needed. That is how a team of about 30 runs the whole platform.
In a real interview, sketch this on the whiteboard before diving into any single box.
Core components
Walk through each service. The interviewer wants to hear what each one owns, not just the names.
Kite client backend
The API and app backend that users talk to, running on AWS across three availability zones in Mumbai. It handles login, watchlists, order entry, positions, funds, and charts. It is stateless where it can be, so it scales horizontally, and it reads almost everything from the Redis hot cache rather than the database.
Real-time ticker
A single Go binary that holds hundreds of thousands of concurrent WebSocket connections and broadcasts market quotes, peaking near 175 million ticks per second. Go was chosen in 2014 specifically for concurrent connection serving after evaluating several languages. Clients subscribe per instrument in a chosen mode, and quotes go out as compact binary frames.
Redis hot cache
The in-memory source of truth for everything Kite shows. Orders, positions, and portfolio are served as O(1) lookups, with a few hundred gigabytes of data kept in memory as byte blobs. This is what lets read-heavy screens return in a few milliseconds and keeps the market-open read surge off the database.
PostgreSQL durable store
The system of record, run as large multi-terabyte instances with hundreds of billions of rows. Zerodha's stated view is that a single well-indexed and partitioned Postgres node scales enormously before any distributed database is needed, so the durable layer stays relational and simple.
Order management system (OMS)
The exchange-facing engine, running on Zerodha's own physical racks in colocation near the exchanges, not on the cloud. It takes an order from Kite, sends it to the exchange over a leased line, and processes acknowledgements and fills. Zerodha runs 8 independent OMS setups across Mumbai and a Chennai disaster-recovery site on 58 servers, using the OmneNest OMS software.
Exchange connectivity
The leased lines and gateways to NSE, BSE, and MCX. Zerodha reports 44 leased lines for primary and backup paths, so a single line or gateway failure does not stop trading. Physical proximity to the exchange keeps order round-trips fast.
Risk and margin engine
The component that checks, before an order goes out, that the user has the funds and margin for it, and that it obeys the applicable limits. It reads from the fast in-memory layer because the check sits on the order path and must be quick.
Reporting and batch pipeline
The end-of-day machinery that produces reports such as contract notes for every client. Zerodha has described generating, digitally signing, and emailing more than 1.5 million contract-note PDFs in about 25 minutes, an example of solving a big batch job with simple, parallel processing rather than heavy infrastructure.
Data model
Pick the right store per table. Justify each choice with the access pattern, not by reflex.
clientsclient_id (PK)namedemat_refbank_refsegment_permissionsstatusThe trading account and what it is allowed to trade. Durable in Postgres. Segment permissions decide whether the client can trade equities, futures and options, commodities, and so on.
instrumentsinstrument_token (PK)symbolexchangesegmenttick_sizelot_sizeThe tradable universe across exchanges, refreshed daily. The instrument_token is what a client subscribes to on the WebSocket and what an order references.
ordersorder_id (PK)client_idinstrument_tokenside (buy|sell)type (market|limit)qtypricestateexchange_order_idcreated_atThe order and its lifecycle. State moves through placed, sent to exchange, open, partially filled, filled, rejected, and cancelled. The exchange_order_id ties it to the exchange's own record. Correctness here is strict.
tradestrade_id (PK)order_id (FK)instrument_tokenqtypriceexecuted_atThe executions that fill an order. A single order can produce several trades if it fills in parts. Trades drive the update to positions and funds.
positionsclient_idinstrument_tokennet_qtyavg_pricerealized_pnlupdated_atThe client's current holding in an instrument, derived from trades. Shown live and recomputed as trades execute and prices move. Kept hot in memory for fast reads.
ticksinstrument_tokenlast_pricebid_offer_depthtsThe live market data. Held in memory and pushed over WebSockets, not written to the durable store at full fidelity. This is the highest-volume data in the system and never touches Postgres on the hot path.
funds_ledgerentry_id (PK)client_iddirection (credit|debit)amount_paisereasoncreated_atThe record of money movement for a client, including trade settlement, charges, and deposits or withdrawals. Append-only so the balance is always reconstructable. Strong consistency required.
Deep dives
These are the conversations the interviewer is steering you toward. Practice each one until you can talk through it without notes.
Streaming market data to hundreds of thousands of clients
The core real-time problem is fan-out. An instrument's price changes many times a second, and every user watching it wants the update at once, so polling a database does not work. Zerodha solves this with a ticker, a single Go binary that holds hundreds of thousands of persistent WebSocket connections and broadcasts quotes to them, peaking near 175 million ticks per second. Two choices make this work. First, the language: Go was picked in 2014 after evaluating others, specifically because it handles very large numbers of concurrent connections well. Second, the wire format: quotes are sent as compact binary frames with prices as integers in paise, and a client subscribes to each instrument in a mode that controls how much data it gets, from a tiny last-traded-price packet up to a full packet with five levels of bid and offer depth. Sending binary rather than JSON, and letting clients ask for only the detail they need, keeps the bandwidth and the per-message work low enough to broadcast to that many connections.
The client-facing and exchange-facing split
Zerodha runs two different environments for two different jobs. The client-facing side, the Kite app and its backend, runs on AWS across three availability zones in Mumbai, because it needs elastic, standard cloud infrastructure to serve a large, spiky user base. The exchange-facing side, the order management system, runs on Zerodha's own physical racks in colocation near the exchanges, connected by leased lines, because order routing to the exchange needs low, predictable latency and direct, reliable links that the public cloud does not give. The order is where the two worlds meet: Kite accepts it in the cloud, hands it to an OMS instance on the colocated racks, which sends it to the exchange over a leased line. Understanding why each half lives where it does, elastic cloud for users and controlled physical infrastructure for the exchange link, is the point the interviewer is looking for.
Redis as the source of truth for what the app shows
The user screens, watchlist, positions, portfolio, and funds, are read constantly, and the read load spikes hard at the market open. Rather than query Postgres on every request, Zerodha keeps the data users see in a hot Redis cache and serves it as O(1) in-memory lookups, with a few hundred gigabytes held as byte blobs. Postgres remains the durable system of record, but the read path goes to memory. This is what lets those screens return in a few milliseconds and, just as important, keeps the market-open surge from hammering the database. The trade to discuss is that the in-memory layer has to be kept in sync with the durable store and rebuilt on failure, which is acceptable because the data can be reconstructed and the read performance is worth it.
The order lifecycle and exchange connectivity
An order is a strict state machine against a system Zerodha does not control. It is placed by the user, sent to the exchange through the OMS, and then the exchange drives it: it can sit open, fill fully, fill in parts across several trades, be rejected, or be cancelled. Each of those events flows back and must update the order, the resulting trades, the position, and the funds, all of which have to reconcile exactly. Zerodha runs this on 8 independent OMS setups across Mumbai and a Chennai disaster-recovery site, on 58 servers, with 44 leased lines to the exchanges for primary and backup paths, so that a single server, line, or gateway failure does not stop trading. The OMS software, OmneNest, is bought rather than built, which is itself a design decision: build the parts that are your edge, such as the ticker and the app, and buy the specialized, regulated exchange gateway.
Surviving the 9:15 market-open surge
The load on a broker is not smooth. A large share of the day's users connect, load their screens, and place orders within minutes of the 9:15 open. The verified way Zerodha absorbs this is structural: the client-facing services are stateless and run across three AWS availability zones so they can be scaled out, and the read-heavy screens are served from the in-memory Redis layer rather than the database, so the surge in reads does not translate into a surge in database load. The ticker, already built to hold hundreds of thousands of connections, carries the price fan-out. The exact operational playbook Zerodha uses for the open, such as any pre-warming or connection ramping, is not something they have published in detail, so in an interview it is honest to describe the structural absorption, stateless cloud services plus an in-memory read layer plus a purpose-built streaming binary, rather than claim specific open-time mechanics.
Doing national scale with a small team and few services
Zerodha runs this platform for millions of clients with a technology team of around 30, and its engineering writing is openly against complexity for its own sake. It warns about microservice sprawl and service meshes adopted for no clear reason, and argues that the large majority of business problems are relational CRUD that a single well-indexed and partitioned Postgres node handles for a very long time before any distributed database is justified. The practical shape of this is few services, each doing a lot, standard and well-understood tools, Go and Postgres and Redis and Nginx, and a preference for simple solutions scaled in simple ways, such as generating 1.5 million contract-note PDFs in about 25 minutes with parallel batch processing rather than a complex pipeline. The interview value of this is judgment: knowing when not to add a service is as much a part of good system design as knowing how to add one.
Trade-offs to discuss
Every senior interviewer expects you to surface at least 3 of these. Pick the decisions, state the alternatives, and justify your choice.
A single streaming binary versus many small services
Breaking the ticker into many services would follow the microservices trend, but it would add network hops and coordination to a job whose whole point is to push data to many connections as fast as possible. A single, well-built Go binary that owns the connections and the broadcast keeps the path short and the operation simple. The cost is that this one service is critical and must be scaled and deployed carefully, which Zerodha accepts because the design is easier to reason about and operate than a distributed alternative.
Colocated physical racks and leased lines versus cloud for exchange connectivity
Running the OMS in the cloud would be simpler operationally, but order routing to the exchange needs low, predictable latency and direct, reliable links, which the public cloud does not guarantee. So Zerodha runs the exchange-facing OMS on its own racks in colocation with leased lines, while keeping the client-facing app on AWS. The cost is owning and operating physical infrastructure, justified because the exchange link is latency-sensitive and reliability-critical in a way the user-facing app is not.
Redis as the read source of truth versus reading from Postgres
Serving user screens directly from Postgres is simpler and always current, but it cannot cheaply absorb the market-open read surge on data that changes constantly. Keeping the hot data in Redis as O(1) in-memory lookups makes reads fast and shields the database, with Postgres remaining the durable record. The cost is keeping the cache in sync with the durable store and rebuilding it on failure, accepted because the data is reconstructable and the read performance matters more.
A single powerful Postgres node versus a distributed database
A distributed NoSQL store is the reflex at this scale, but it gives up the relational integrity and ACID guarantees that orders, trades, and funds need, and it adds operational complexity. Zerodha's position is that a single well-indexed and partitioned Postgres node, handling hundreds of billions of rows, is enough for the large majority of the workload. The cost is that a single node has a ceiling and needs careful indexing and partitioning, which they judge far cheaper than running a distributed system prematurely.
Binary WebSocket frames versus JSON
JSON quotes would be easier to work with, but at hundreds of millions of ticks per second the size and parsing cost of JSON is too high. Zerodha sends compact binary frames with prices as integers in paise and lets clients subscribe in a mode that controls how much detail they receive. The cost is a more complex client that has to decode the binary format, accepted because it is the only way to keep the bandwidth and per-message work low enough at this fan-out.
Building the app and ticker in house versus buying the OMS
Zerodha builds the parts that are its edge, the trading app and the real-time ticker, and buys the order management system, OmneNest, which is a specialized, regulated exchange gateway. Building everything would be slower and would mean maintaining a regulated exchange connector that offers no product advantage, while buying everything would give up control of the user experience. Splitting build and buy along the line of what is actually a differentiator is the judgment being tested.
How Zerodha actually does it
Most of this is documented by Zerodha directly, on its engineering blog and its business-update posts. Zerodha has stated that its client-facing Kite platform runs on AWS across three availability zones in Mumbai, that everything shown on Kite is served from a hot Redis cache as O(1) in-memory lookups with a few hundred gigabytes held in memory, and that PostgreSQL is the durable store, run as large multi-terabyte instances with hundreds of billions of rows. It has described the ticker as a single Go binary serving hundreds of thousands of concurrent WebSocket connections and broadcasting millions of quotes per second, peaking around 175 million ticks per second on 4 June 2024. The Kite Connect documentation specifies the streaming protocol: subscribe to instruments per connection, receive compact binary frames with prices in paise, in modes from last-traded-price up to a full packet with five levels of market depth. Zerodha has reported running 8 independent OMS setups across Mumbai and a Chennai disaster-recovery site, on 58 servers, with 44 leased lines to NSE, BSE, and MCX, using the OmneNest OMS software, and generating 1.5 million contract-note PDFs in about 25 minutes. Its engineering writing openly argues against microservice sprawl and for a Postgres-first, few-services design, and it runs the platform for millions of clients with a technology team of around 30. Two accuracy notes for the interview. First, on client counts, Zerodha had about 7.9 million NSE active clients at the end of FY25, ranking second after Groww, so describe it as one of India's largest brokers or number two by NSE active clients, not the largest. Second, the exact operational mechanics of the 9:15 market open, such as pre-warming, are not published in detail, so describe the structural way the design absorbs the surge rather than claiming specific open-time steps.
Sources
- Zerodha Tech, Scaling with common sense: the Go ticker, Redis hot cache, Postgres-first, and anti-microservices philosophy
- Zerodha Z-Connect, Zerodha's infrastructure upgrades: 8 OMS setups, 58 servers, 44 leased lines, AWS three-AZ Mumbai, 175M ticks per second peak
- Kite Connect v3 WebSocket docs: the streaming protocol, binary frames, modes, and market depth
- Zerodha Tech, 1.5 million PDFs in 25 minutes: batch processing done simply
- Zerodha open-source organization on GitHub, including dungbeetle and the Kite Connect clients
- Business Today, Zerodha runs at scale with about a 30-person team and no full-time product managers
Lessons to study before this interview
If any of these topics are fuzzy, the interviewer will catch it. Each lesson is 15 to 60 minutes with diagrams, code, and a quiz.
WebSockets
intermediate / messaging event systems
Message Queues
intermediate / messaging event systems
Cache-Aside Pattern
foundation / caching strategies
Database Sharding
foundation / database fundamentals
Load Balancing
foundation / core fundamentals
High Availability
advanced / reliability resilience
Rate Limiting for Resilience
advanced / reliability resilience