What Uber and DoorDash Actually Got Right (and Wrong) About On-Demand Apps
· 6 min read · Mona Technologies
Every founder pitching an on-demand app describes it as "Uber for X" and means the app. That's the wrong unit of analysis. Uber and DoorDash aren't apps that happen to move cars and food — they're real-time matching engines with a thin app layer on top. If you build the app first and treat matching, pricing, and dispatch as features to bolt on later, you'll end up rebuilding the core of your product after launch, which is exactly what both companies had to do.
The app is not the product — the matching loop is
Uber's surge pricing exists for a specific structural reason: the company can't order drivers to show up. Uber's own explanation of the mechanism is blunt about this — as a platform, it has no way to mandate driver availability, so price is the only lever it has to pull more supply onto the road during a demand spike, and to push demand back down when supply is thin. That's not a pricing feature, it's the entire business model's balancing mechanism. If you're building a two-sided marketplace (drivers/riders, cooks/eaters, freelancers/clients, whatever your version is), the question to answer before a single UI screen gets designed is: what happens in your system in the 90 seconds after supply and demand go out of balance? If the honest answer is "nothing, we haven't built that," you don't have a marketplace yet — you have a directory with a checkout button.
- Define your matching rule in plain language before wireframing: first-available, closest, highest-rated, or price-weighted.
- Decide what happens when there's a supply shortfall — do you throttle demand (surge/waitlist), queue it, or silently degrade service quality?
- Build the matching and dispatch logic as its own service from day one, even at tiny scale — retrofitting it later means rewriting your data model, not just your UI.
DoorDash's monolith mistake is the mistake most founders are about to make
DoorDash didn't start as a distributed system — it started, like almost every startup, as a single monolithic codebase, and only began migrating off it years into the company's life as scale exposed the cracks. That's not a failure; it's the normal, correct sequence for an early-stage product, because a monolith is faster to build and easier to change when you don't yet know what your product is. The lesson for a founder building an on-demand app today isn't "start with microservices" — that's usually premature and expensive. The lesson is narrower: know in advance which one or two components (matching, payments, real-time location) you will need to pull out and scale independently the moment volume shows up, and design your data boundaries so that extraction is a refactor, not a rewrite. Guessing wrong here is expensive later; guessing right costs you almost nothing now.
Real-time location tracking is a cost center, not a feature checkbox
Founders routinely scope "live tracking" as one line item alongside push notifications and ratings, when in reality it's the single most expensive piece of infrastructure in an on-demand app. Every active courier or driver is a continuous stream of location updates that has to be ingested, matched against a live map, and pushed back out to the right customer's screen within a couple of seconds — at whatever concurrency you have live at that moment. Uber's engineering documentation on their real-time data platform describes exactly this kind of pipeline: high-volume streaming ingestion feeding low-latency lookups, built specifically because generic databases weren't fast enough for the location-matching use case. You don't need Uber's scale to need Uber's discipline: decide early whether you're building this yourself on a managed real-time database (Firebase, Supabase Realtime, Ably) or a custom pipeline, because the two have wildly different cost curves as your active-user count grows, and switching later means migrating live production traffic.
- Estimate cost per concurrent active session, not per registered user — that's what actually drives your infrastructure bill.
- Use a managed real-time backend until you have a specific, measured reason not to; custom real-time infrastructure is a multi-month investment most startups can't justify pre-product-market-fit.
- Set an explicit location-update frequency (e.g. every 4-6 seconds, not every second) — it's a direct lever on both battery drain and server cost.
Trust and safety is part of the product, not a policy page
Both companies learned, expensively and publicly, that a marketplace connecting strangers in the physical world needs identity verification, in-app communication that doesn't expose personal phone numbers, and a dispute-resolution flow built before launch, not after the first bad incident. This isn't a legal afterthought you hand to a lawyer once you have users — it changes your onboarding flow, your data model (you need audit trails on every match and message), and your support tooling from the start. If your MVP plan has trust-and-safety as a "phase 2" item, move it to phase 1; it's cheaper to build once than to retrofit onto live user data.
The short version
Uber and DoorDash's real product was never the app — it was a real-time system for balancing supply and demand under pressure, with the app as the visible tip of it. Before you spec another screen, spec your matching rule, your shortfall behavior, and which piece of infrastructure will need to scale independently first. Get that right and the app itself is the easy part.
