Loading...

How Zomato Actually Works

A deep dive into Zomato's architecture, why 'your food is 32 minutes away' is a genuinely hard machine learning problem and not a maps calculation, the event-driven backbone moving hundreds of millions of messages a minute, and the database migration story that shows what happens when a system built for one kind of scale meets an entirely different one.

By udthedeveloper•12 min read•
2 views
How Zomato Actually Works

Open Zomato at 8:45pm on a Saturday and the app tells you, with a straight face, that your biryani is 32 minutes away. Not "20 to 40 minutes." Not "soon." Thirty-two. That number has to survive a restaurant kitchen that's currently backed up, a delivery partner who might be stuck behind a wedding procession, and a monsoon downpour that started four minutes ago and wasn't in anyone's forecast reaching a genuinely confident, specific number for an event that hasn't happened yet is a much harder problem than it looks like from the customer's side of the screen, and Zomato has rebuilt its answer to that problem more than once.

This article looks at how Zomato is actually built to make that promise mostly true: why estimated arrival time is treated as its own dedicated machine learning system rather than a maps lookup, the Kafka-powered event backbone that lets hundreds of independent microservices react to a single order without ever talking to each other directly, and a genuinely revealing database migration story straight from Zomato's own engineering blog about a billing system that outgrew the database it was built on. Zomato runs one of the more detailed public engineering blogs among Indian tech companies, so most of this draws directly from Zomato Engineering's own posts, alongside independent technical breakdowns filling in the surrounding picture.

Illustration of a food delivery ETA countdown against a city map

Why "Distance Divided by Speed" Was Never Going to Work

A piece on Zomato's own engineering blog, written by the team that owns this exact problem, states plainly why ETA sits at the centre of the entire product: it's used across menu browsing, restaurant selection, delivery partner assignment, order tracking, and delay communication, and a dedicated internal Time Microservice owns the computation and distributes it out to every other service that needs it. The same post is specific about what actually goes into that number Zomato's ETA isn't just delivery partner travel time, it also factors in kitchen preparation time, real-time dynamic buffers, and localized arrival behaviour at the customer's specific address. Early versions of the system leaned on a map-graph-based routing model to estimate travel time, but the team found the forecasted route could differ significantly from the route a delivery partner actually took in practice, which pushed them toward a tree-based prediction model instead one trained on how partners genuinely move through a city, not just how the road network says they should.

A second post in the same series, Part Two, goes further into how that prediction connects back into dispatch itself: as a byproduct of feature engineering for the ETA model, the team built an equation-based, ultra-fast ETA derived from a delivery partner's speed and "medal" history, which alone improved the accuracy of the delivery-partner-assignment system's own predictions by 4 percent. The same post is candid about a deliberate design choice most users never think about: Zomato doesn't share the raw predicted ETA with delivery partners or show them a countdown, specifically because a visible timer could create a sense of on-road urgency and encourage rash driving.

A restaurant's own head server, who doesn't just glance at a clock to guess when your table's food will be ready, but actually knows that specific kitchen's real rhythm today the fryer that's running slow, the fact that table 12 just ordered the dish that takes longest, how the rain outside is keeping delivery bikes idling a beat longer than usual. A generic "distance divided by average speed" calculation is the equivalent of a server who's never worked a shift in that kitchen; Zomato's ETA system is built to behave like the one who has.

Naive ETA:
  distance ÷ average speed = ETA
  → Ignores kitchen load, live traffic, weather, individual rider behaviour
 
Zomato's ETA (Time Microservice):
  Kitchen Preparation Time (learned per restaurant, per hour)
  + Delivery Partner travel time (tree-based model, trained on actual routes taken)
  + Real-time dynamic buffers (traffic, weather, local arrival quirks)
  → A single number, recomputed continuously, fed back into dispatch itself
Diagram of Zomato's ETA system combining kitchen, travel, and buffer predictions

Picking a Delivery Partner Is Not the Same as Picking the Nearest One

Knowing how long an order will take is only useful if it feeds into who actually delivers it. A breakdown on Medium makes the underlying point clearly: once a food preparation ETA is known, the app has to assign the best possible delivery partner, and "best" deliberately does not mean "nearest." A partner sitting one block away but facing a closed road, or already midway through another delivery, can easily be a worse choice than someone slightly further off with a clear run. A separate technical breakdown on Optiblack adds that Zomato's models continuously adapt to live conditions, recalculating routes and reassigning delivery partners on the fly rather than locking in a decision the moment an order is placed and hoping conditions hold.

A dispatcher at a busy taxi stand who doesn't just send the first cab in line, but actually knows which driver is about to finish a job two streets over, which one is stuck behind roadwork, and which one genuinely has the clearest path to the pickup point right now the closest car on paper is very often not the fastest car in practice, and a good dispatcher (human or algorithmic) has to weigh both at once, continuously, rather than deciding once and walking away.

One Order, Many Services, Zero Services Talking Directly to Each Other

Zomato's own recap of its New Year's Eve 2023 traffic, "A Tale of Scale: Behind the Scenes at Zomato Tech for NYE 2023", gives a genuine sense of the scale this runs at: benchmarking alone had to account for more than 300 microservices, and on the night itself, Kafka the backbone of Zomato's event-driven architecture handled a peak rate of over 450 million messages per minute, with clusters reaching a total peak throughput of 5.6 GBps. The same post notes that LogStore, Zomato's in-house logging platform, processed 60 terabytes of application logs that same day, peaking at an 80 million-requests-per-minute ingestion rate, and that even against that level of demand, 60% of orders were still delivered within 30 minutes.

A breakdown on Medium explains why an event backbone like this matters structurally, not just for volume: when an order is placed, an event gets published to Kafka, and services like Order, Payment, and Delivery each subscribe to that event and process it independently, without blocking on one another or needing to call each other directly. Kafka also powers Zomato's notification system this way, pushing out real-time updates on order status and delivery partner assignment as those events happen, rather than the app having to repeatedly ask each service "has anything changed yet?"

A newsroom's wire service, where a single incoming story gets published once to the wire, and the sports desk, the politics desk, and the metro desk each independently decide what to do with it, on their own schedule, without the original reporter needing to personally walk over and hand a copy to every single desk in the building. That's the actual value of an event bus like Kafka here: the Order service doesn't need to know that Payment, Delivery, and Notifications all care about what just happened it just publishes the event once, and lets every interested service pick it up on its own terms.

Order placed:
  Order Service → publishes "order.created" event to Kafka
    → Payment Service subscribes, processes payment independently
    → Delivery Service subscribes, begins partner assignment independently
    → Notification Service subscribes, pushes real-time status update independently
  None of these services call each other directly.
  None of them block waiting on the others to finish.
Diagram of Kafka decoupling order, payment, delivery, and notification services

When the Database That Got You Here Can't Take You Further

This is a genuinely candid engineering story, and it comes straight from Zomato's own blog. In "Unlocking Performance, Scalability, and Cost-Efficiency of Zomato's Billing Platform by Switching from TiDB to DynamoDB", the team lays out the original design: Zomato's Billing Platform followed an asynchronous, Kafka-based messaging approach to integrate independent microservices in a loosely coupled way, acting as both a producer and consumer of billing-order events, processing them, and producing a processed ledger for various downstream business needs. That architecture had originally been built on TiDB, an open-source distributed SQL database chosen specifically because it combines the horizontal scalability of NoSQL systems with the ACID compliance of a traditional relational database a genuinely reasonable choice for a billing system that needs both scale and correctness.

The honest part of the post is admitting that reasonable choice eventually stopped being the right one as the platform's performance, scalability, and cost requirements shifted, prompting the team to migrate the underlying datastore to DynamoDB instead. It's a useful reminder buried inside an otherwise very technical migration post: even a well-justified, deliberately chosen piece of infrastructure has a shelf life, and outgrowing it isn't a sign the original decision was wrong, just that the business it was serving didn't stay still.

A growing company that outgrows its first office not because leasing that office was a mistake, but because the team that fits in five desks eventually becomes a team that needs fifty, and at some point the honest move is packing up and moving, not squeezing in more desks. Zomato's TiDB-to-DynamoDB migration is that same story, told in database engines instead of square footage.

Making Real-Time Data Processing Something Any Team Can Use

A post on Zomato's engineering blog, "Apache Flink Journey @ Zomato: From Inception to Innovation", describes a different kind of scaling problem: not handling more data, but making the tools for handling that data usable by teams who aren't stream-processing specialists. The post describes building a self-serve Flink platform, powered by the Flink Kubernetes Operator, complete with its own metrics and alerting system and a dedicated logging setup where a sidecar container runs alongside each Flink job manager and task manager, shipping logs into LogStore so teams can debug their own pipelines without needing to loop in the platform team every time something breaks.

A related post, "Eliminating Bottlenecks in Real-Time Data Streaming: A Zomato Ads Flink Journey", shows what that self-serve platform enabled downstream: the Ads team was managing large state pipelines, some exceeding 150 GB, and by migrating from Flink Java to Flink SQL, the team achieved a 99% reduction in state size and cut monthly infrastructure costs by over $3,000, while eliminating downtime in the process.

A well-organized shared kitchen in a food hall, where any individual vendor can walk in and start cooking on professional-grade equipment without needing to personally install, wire, and maintain a commercial oven themselves. A self-serve stream processing platform does the same thing for engineering teams inside Zomato: the Ads team doesn't need to become stream-processing infrastructure experts to get a 99% smaller, cheaper, more reliable pipeline they just need the platform someone else already built to work.

Closing illustration summarizing Zomato's ETA, dispatch, and event-driven architecture

A Fair Note on What's Publicly Known Here

It's worth being upfront about the shape of this article: Zomato's engineering blog is genuinely detailed on the systems it chooses to write about ETA modelling, the Flink data platform, and specific database migrations especially but it's noticeably quieter on some other core pieces, like the exact internals of restaurant search and ranking or the full details of its fraud-detection systems. Some of the connective material here, particularly around how the 300-plus microservices mentioned in the NYE 2023 post are organized day to day, is pieced together from independent technical breakdowns and architecture write-ups rather than a single first-party document describing the whole system end to end. The ETA modelling, Kafka-based event architecture, and the TiDB-to-DynamoDB migration all rest on genuinely solid, first-party ground straight from Zomato's own engineering team.

Putting It Together

None of the individual pieces here are exotic inventions on their own. Event-driven microservices, tree-based prediction models, and self-serve data platforms are all recognizable patterns across the wider industry. What makes Zomato's story genuinely interesting is how tightly the ETA problem sits at the center of nearly everything else the number the customer sees isn't just a courtesy estimate, it's the output of a system that also has to feed delivery partner assignment, and that assignment decision has to react to real-time events flowing through Kafka fast enough to still be useful, all while the underlying data infrastructure keeps getting rebuilt underneath it, from database engines to stream-processing platforms, as the actual scale of the business keeps changing shape.

What This Means Going Forward

As Zomato keeps expanding into adjacent businesses quick commerce through Blinkit, B2B restaurant supply through Hyperpure, and increasingly its own logistics infrastructure the same underlying tension keeps reappearing in a new form: an ETA model trained on how a delivery partner moves through a city on a two-wheeler with a food bag is a genuinely different modelling problem than predicting a ten-minute grocery delivery from a dark store, or a B2B ingredient delivery to a restaurant's back door on its own schedule, and stretching one prediction system comfortably across all three is a real, ongoing engineering challenge rather than a solved one. The lesson underneath Zomato's story isn't really about Kafka, Flink, or DynamoDB specifically. It's the same one running through this whole series, just wearing a food-delivery-shaped costume: the hardest problems are rarely the ones with a single dramatic fix, they're the quiet, continuous ones like predicting a number that has to keep being right, order after order, no matter what the city throws at it that day.

Discussion