18px
System Design·March 20, 2026·8 min read

Why Your Swiggy ETA Jumps Mid-Order — The 4 ML Models Behind "35 Min Delivery"

That mid-order ETA bump is not random. It is the result of four independent prediction legs being stitched together and partially re-run when real-time signals diverge.

Why Your Swiggy ETA Jumps Mid-Order — The 4 ML Models Behind "35 Min Delivery"

"35 min delivery" is not a number. It is four independent ML models pretending to be one number.

You have seen it happen. Swiggy says 35 minutes. You wait. At some point, mid-order, it quietly jumps to 48 minutes. No explanation. Just a bigger number.

Most people assume it is a bug, or that Swiggy is just being conservative. The reality is more interesting: that bump is the result of real-time signals diverging from four separate prediction models that were stitched together when you placed your order.

This post breaks down exactly how it works, and how Swiggy and Zomato do it differently.

The Core Insight: One Number, Four Models

  • Marketplace dynamics: is there an exec available to take the order?

  • Road traffic: how fast can the exec move through the city?

  • Restaurant operations: how fast is this specific kitchen working right now?

Four ETA legs diagram showing assignment, first mile, wait time, and last mile
Four ETA legs diagram showing assignment, first mile, wait time, and last mile

The Four Models — What Each One Actually Does

Model 1: Order-to-Assignment

Model 2: First Mile

Model 3: Restaurant Wait Time

Multi-input neural network style diagram for ETA prediction
Multi-input neural network style diagram for ETA prediction

Model 4: Last Mile

How the Final ETA Is Computed

Why the ETA Bumps Mid-Order

  • Traffic worsens because a jam appears on the route

  • Restaurant stress spikes because the kitchen starts falling behind

  • The exec gets stuck, delayed, or takes a detour

When real-time signals diverge significantly from the initial prediction, the platform re-runs the affected legs. If the new total exceeds the original by more than a threshold, typically around five minutes, it triggers a bump: the ETA update you see on screen.

Critically, not all four legs are re-predicted. Assignment and First Mile are usually locked by the time a bump occurs. Only WaitTime and LastMile remain live until pickup and dispatch are clearer.

Example:

T+0 Initial prediction -> 35 min stress_signal = 0.7 traffic_factor = 1.8x

T+8 Real-time update stress_signal -> 0.95 traffic_factor -> 2.4x

WaitTime re-predicts: +5 min LastMile re-predicts: +3 min

New total -> 43 min

Swiggy's Bump Quality Metric

Swiggy vs. Zomato — Same Number, Different Architecture

  • Swiggy: four explicit leg models stitched together

  • Zomato: a more layered stack with prep-time and delivery ETA modeled separately plus dynamic buffering

  • Prep time: Swiggy treats it as one ETA leg, while Zomato invests more deeply in a standalone Bidirectional LSTM

  • Last mile: Swiggy uses its own model stack, while Zomato leans heavily on delivery-partner GPS and tree-based delivery ETA logic

  • Maps: Zomato enriches open maps using its own delivery-partner pings to reconstruct roads and find shortcuts missing in dense Indian areas

  • Explainability: Swiggy emphasizes debugging and bump quality, while Zomato emphasizes per-window ETA compliance and route enrichment

Zomato's map enrichment is especially clever. OpenStreetMap is incomplete in many dense Indian zones, so delivery-partner GPS traces can be used to reconstruct missing roads and last-mile shortcuts. Same user-facing number, very different backend investment.

The Go Prototype

What the prototype does:

  • Takes an OrderContext as input with fields like exec distance, traffic factor, queue depth, and stress signal

  • Runs all four leg functions independently

  • Stitches them into a final ETA breakdown

  • Accepts updated real-time signals in a second call

  • Re-runs only WaitTime and LastMile

  • Emits a bump event if the delta exceeds threshold, including trigger leg and reason

Sample output:

text=== ETA Engine: Order #8821 ===

[Model 1] Assignment      ->  5.0 min  (supply_ratio: 0.37, peak: true)
[Model 2] First Mile      ->  7.6 min  (dist: 1.4km, traffic: 1.8x)
[Model 3] Restaurant Wait -> 23.6 min  (queue: 6, stress: 0.70)
[Model 4] Last Mile       -> 20.3 min  (dist: 2.1km, junction_penalty: +8min)
--------------------------------------
         Quoted ETA        -> 57 min

T+8: Real-time divergence detected
   Restaurant stress: 0.70 -> 0.95
   Traffic factor:   1.80 -> 2.40

[Model 3] Wait (revised)  -> 27.6 min  (+4.0)
[Model 4] Last Mile (rev) -> 25.1 min  (+4.8)
--------------------------------------
         Revised ETA       -> 66 min   BUMP (+9 min)
   Trigger: WaitTime + LastMile divergence
   Reason:  restaurant_stress_spike + traffic_divergence

Key Takeaways

The next time your ETA jumps, you will know exactly which model changed its mind, and why.

Filed under fieldnotesMarch 20, 2026