- 🔥Connect: https://xam-heisenberg-company.vercel.app/
- 🔥GitHub: https://github.com/Subham-Maity
- 🔥Twitter: https://twitter.com/TheSubhamMaity
- 🔥LinkedIn: https://www.linkedin.com/in/subham-xam
- 🔥Insta: https://www.instagram.com/subham_xam
Quick Commerce Order & Delivery Flow
A step-by-step logic guide. Read it top to bottom and you can build the whole order-to-delivery part. No code here, only the thinking.
1. The Big Picture
Q: What are we building?
The order and delivery engine of a quick commerce app, like Zepto, Blinkit, Swiggy Instamart, Zomato or Flipkart Minutes.
Q: Why is quick commerce different from normal e-commerce?
The user wants the order immediately. The promise is delivery in about an hour or less. Every minute wasted anywhere in the flow hurts that promise.
Q: What problem are we solving?
The user should never get food, groceries or any product late. The system must find a delivery person fast, and must never leave an order stuck without anyone looking at it.
Q: Who should find the delivery person, the vendor or the system?
The system. The vendor (for example a restaurant owner) is busy cooking and serving his own customers. He cannot also call drivers. Finding a driver is our app's job, not his.
2. Who Is Involved
| Role | What they do in this flow |
|---|---|
| User (Customer) | Places the order, receives the delivery OTP, gives it to the driver at the door |
| Vendor | Receives the order, accepts or rejects it, prepares it, gets the pickup OTP, gives it to the driver |
| Driver | Receives delivery requests, accepts one, picks up, delivers |
| Admin | Sets the rules (radius, timeouts), receives alerts when the system cannot find a driver, assigns a driver manually |
| System (Backend) | Runs the logic, filters drivers, sends notifications, tracks every status |
3. Two Kinds of Status (Keep Them Separate)
An order has two different lives. Do not mix them into one column.
Order status answers: where is the order in its journey?
| Order Status | Meaning |
|---|---|
| PLACED | User created the order |
| VENDOR_ACCEPTED | Vendor said yes |
| VENDOR_REJECTED | Vendor said no (end of the line) |
| PREPARING | Vendor is making or packing it |
| READY | Order is ready to be picked up |
| PICKED_UP | Driver collected it (pickup OTP verified) |
| OUT_FOR_DELIVERY | Driver is travelling to the user |
| DELIVERED | User's OTP verified (end of the line) |
| CANCELLED | Stopped by user, vendor or admin |
Dispatch status answers: how is the search for a driver going?
| Dispatch Status | Meaning |
|---|---|
| NOT_STARTED | Vendor has not accepted yet |
| SEARCHING | System is looking for drivers nearby |
| REQUEST_SENT | Nearby drivers have been notified |
| ASSIGNED | One driver accepted |
| NEEDS_ADMIN | No driver found in time, admin must assign |
| MANUALLY_ASSIGNED | Admin picked a driver |
Q: Why two separate statuses?
Because "searching for a driver" and "being prepared by the vendor" happen at the same time. One status column cannot say both.
Also keep a status history. Every time any status changes, save one row: which order, old status, new status, who did it (user, vendor, driver, admin, system) and when. This is your proof when there is a dispute or refund.
4. The Settings Admin Controls
Nothing below should be fixed inside the code. The admin changes them from a settings screen.
| Setting | Example value | Why it exists |
|---|---|---|
| Driver search radius | 3 to 5 km (quick commerce), can be raised for bigger areas | Decides which drivers are "near enough" |
| Wait time for driver response | 60 to 90 seconds per search round | Keeps the 1-hour promise |
| Total search time before admin alert | 3 to 4 minutes | Order must not sit unattended |
| Max wrong OTP attempts | 3 to 5 | Stops guessing |
| OTP expiry time | A few minutes after it is created | Old OTPs become useless |
| Vendor response time limit | 2 to 3 minutes | Auto-cancels if the vendor ignores the order |
| Driver location freshness limit | 30 to 60 seconds | Ignores drivers whose location is outdated |
5. The Main Flow
Step 1: User places an order
Q: What happens first?
The user places an order. The system saves it with order status PLACED and dispatch status NOT_STARTED.
Q: What does the order need to carry?
User, vendor, items, delivery address with the user's latitude and longitude, and the time it was placed.
Step 2: The order reaches the vendor
Q: Who gets the order first?
The vendor. His app shows it in his order list, and the system also sends him a push notification (FCM, Firebase Cloud Messaging).
Q: Is the push notification enough?
No. Notifications can be late or lost. Treat the notification as a wake-up call only. The order is always saved in the database first, and the vendor's app should also load pending orders from the backend whenever it opens or refreshes. The database is the truth, the notification is just a nudge.
Step 3: The vendor accepts or rejects
Q: What if the vendor is closed, out of stock or too busy?
He can reject the order. The order becomes VENDOR_REJECTED, the user is told, and nothing else happens.
Q: What if the vendor does not respond at all?
After the vendor response time limit, the system cancels the order and tells the user. A silent vendor must not block the user.
Q: When does the driver search start?
As soon as the vendor accepts. Order status becomes VENDOR_ACCEPTED, dispatch status becomes SEARCHING.
Q: Should we wait for the food to be fully ready before looking for a driver?
No, that wastes time. Start the search at acceptance. The vendor tells the app a prep time (for example 10 minutes). The idea is that the driver arrives around the time the order is ready, not 15 minutes too early and not 15 minutes too late.
Step 4: Finding the right drivers
Q: Imagine the app has 10 drivers but only 3 are near this vendor. Do we notify all 10?
No. Notifying everyone annoys drivers who are far away and floods their phones. We notify only nearby, suitable drivers.
Q: How does the system know where the vendor and drivers are?
| Who | Location source | Changes? |
|---|---|---|
| Vendor | The vendor's address, saved with latitude and longitude when the store is created (the frontend sends them to the backend at that moment) | No, fixed |
| Driver | The driver's app keeps sending the current latitude and longitude to the backend every few seconds while the driver is online | Yes, always moving |
Q: Why can't driver location be saved once, like the vendor's?
Because a driver moves. A location saved at signup is useless. Only the latest location counts.
Q: What filters decide who gets the request?
All of these must be true:
| Check | Question the system asks |
|---|---|
| 1. Online | Is the driver switched on and available for work? |
| 2. Free | Is the driver not already carrying another order? |
| 3. Fresh location | Was his location updated within the freshness limit? |
| 4. Close enough | Is he within the admin's radius from the vendor? |
Q: How do we measure "close enough"?
With the Haversine formula. It takes two latitude/longitude pairs (vendor and driver) and returns the straight-line distance in km. The system does this for every online and free driver, then keeps only those at or under the radius.
Q: Example?
Radius is set to 5 km. Ten drivers are online. Haversine says: Driver A 1.2 km, B 3.8 km, C 4.6 km, the other seven are 7 to 15 km. Only A, B and C pass.
Q: Is straight-line distance always accurate?
No. Roads, flyovers and one-way streets make the real route longer. For a first version this is acceptable. Later you can use a maps routing service to improve accuracy on the short list.
Step 5: Sending the delivery request
Q: What happens with the 3 selected drivers?
They all get a "new delivery request" notification, and the request also appears in their request list in the app (same rule as before: database is truth, notification is a nudge).
Q: What does the driver see?
Pickup place, distance to the vendor, drop area, and the earning. Dispatch status becomes REQUEST_SENT.
Q: What if the first round gets no response?
Wait the configured response time (for example 60 to 90 seconds). If nobody accepts, the system can repeat once with a wider radius if the admin allowed it. Then it moves to the admin fallback.
Step 6: A driver accepts, first one wins
Q: What if two drivers tap Accept at nearly the same moment?
Only one may win. The rule: "assign this order to this driver only if the order still has no driver." The check and the assignment must happen as one single, indivisible step in the database. If the order is already taken, the second driver sees "This order was already taken."
Q: Why is this important?
Without it, two drivers could both think the order is theirs and both drive to the vendor.
Q: What happens after the winner is decided?
- Dispatch status becomes ASSIGNED
- The order is added to that driver's order list
- The other drivers' requests disappear from their screens
- The driver is now marked "busy"
- User and vendor are told a driver is coming
Step 7: When no driver can be found
Q: What if nobody is within the radius?
The system alerts the admin right away. Dispatch status becomes NEEDS_ADMIN.
Q: What if drivers were within the radius, were notified, but nobody accepted before the time ran out?
Same result. The admin gets the alert.
Q: What does the admin do?
Chooses any driver, no matter where that driver is, and presses Assign. The order is put into that driver's order list and dispatch status becomes MANUALLY_ASSIGNED.
Q: How does the admin actually get that driver to go?
That is the admin's own business: a phone call, WhatsApp, or their own logistics. Our system does not need to handle it. Once the admin assigns, it is the app owner's responsibility that the order is delivered.
Q: Where must the timer for the "wait, then alert admin" live?
In something that survives a server restart (a saved job in a job queue or a saved "deadline time" in the database). A timer that lives only in the server's memory disappears when the server restarts, and the order would be forgotten forever.
Step 8: Pickup, the vendor OTP
Q: Why do we need an OTP at pickup?
It proves the right driver met the right vendor and took the right order. Nobody can claim "I never gave it" or "I never got it."
Q: Who sees the pickup OTP?
Only the vendor, inside the vendor's app. The driver must not see it in advance.
Q: When is the vendor's OTP created?
When a driver is assigned (either by accepting or by admin).
Q: What does the driver do?
Goes to the vendor, status can show "arrived at vendor," and asks for the product. The vendor tells the OTP. The driver types it into his app.
Q: What happens when the OTP is correct?
Order status becomes PICKED_UP, then OUT_FOR_DELIVERY.
Q: What if the OTP is wrong?
The driver may try only the allowed number of times. After that, the app blocks further tries and the admin is alerted to resolve it.
Step 9: Delivery, the user OTP
Q: When is the user's OTP created and shown?
When the order becomes OUT_FOR_DELIVERY. It is shown only in the user's app.
Q: What does the driver do?
Reaches the user, hands over the product, and asks for the OTP. The user tells it. The driver types it into his app.
Q: What happens when it is correct?
Order status becomes DELIVERED. The driver becomes free again and can receive new requests.
Q: What if the user is not reachable or refuses to share the OTP?
The driver reports "customer not available." The admin is alerted and decides (wait, retry, return, cancel). Never let the driver mark an order delivered without an OTP or an admin decision.
6. OTP Rules (Both OTPs)
| Rule | Why |
|---|---|
| Pickup OTP goes only to the vendor, delivery OTP only to the user | The driver must not know them beforehand |
| Each OTP is linked to one order | It cannot be reused on another order |
| Each OTP expires after a short time | Old OTPs become useless |
| Limited wrong attempts | Stops guessing |
| Store OTPs in a protected form, not as plain readable text | If the database leaks, OTPs stay safe |
| Every successful and failed attempt is recorded | Needed for disputes |
7. What If Something Goes Wrong
| Situation | What the system does |
|---|---|
| Vendor rejects | Order → VENDOR_REJECTED, tell the user |
| Vendor never responds | Auto-cancel after the time limit, tell the user |
| User cancels before the driver picks up | Allowed, order → CANCELLED, free the driver if one was assigned |
| User cancels after pickup | Not allowed in the normal flow, only admin can decide |
| Driver cancels after accepting | Remove him from the order, put the order back into driver search, alert admin if it keeps happening |
| Driver goes offline mid-order | Alert admin, who can reassign |
| Vendor takes too long to prepare | Alert admin and inform the driver and user of the delay |
| Wrong OTP too many times | Block further tries, alert admin |
| Server restarts during a search | Search continues because the deadline was saved, not kept only in memory |
| Notification not delivered | Apps also load pending requests from the backend, so nothing is lost |
8. Refunds
Covered later as a separate section. Because every status change is already recorded in the history table, refunds will be able to look at exactly what happened and when.
9. Suggested Build Order for a Beginner
| Order | Build this | Why this order |
|---|---|---|
| 1 | Roles and login (user, vendor, driver, admin) | Everything depends on knowing who is who |
| 2 | Vendor store with saved latitude and longitude | Needed for distance |
| 3 | Driver online/offline toggle and live location updates | Needed for the driver filter |
| 4 | Order creation and the two statuses plus history table | The backbone of everything |
| 5 | Vendor accept/reject screen | Starts the dispatch |
| 6 | Admin settings screen (radius, timeouts, OTP limits) | Rules must be configurable before dispatch logic uses them |
| 7 | Driver filter (online, free, fresh location, Haversine within radius) | The core of the dispatch |
| 8 | Delivery request list for drivers and the "first accept wins" rule | The race-safe assignment |
| 9 | Timeout and admin alert, then manual assign | The safety net |
| 10 | Pickup OTP | First handshake |
| 11 | Delivery OTP | Second handshake |
| 12 | Cancellation and failure cases from section 7 | Makes it real-world ready |
10. Quick Glossary
| Term | Plain meaning |
|---|---|
| FCM | Google's push notification service. It taps the phone to say "something new is waiting" |
| Haversine | A formula that gives the straight-line distance in km between two latitude/longitude points |
| Radius | The maximum distance from the vendor within which drivers are considered |
| Dispatch | The process of finding and assigning a driver |
| OTP | A short one-time code used as proof of a handoff |
| Job queue | A saved to-do list for the server, so scheduled tasks survive restarts |
| Source of truth | The place (the database) that is always right when other things disagree |
