UberEats: Deconstructing a Big Service

One order, three sides, and a phone that can lose its connection.

Concept. UberEats must keep the diner, driver, and restaurant in agreement while the service runs across many machines. Uber's fulfillment platform uses a distributed SQL database for shared state. Its driver app saves unfinished actions on the phone.

Intuition. One burrito order changes several pieces of state. The database applies the related changes together and makes one driver assignment win. If the phone loses its connection, it saves the driver's action and sends it when the connection returns.

Case Study Reading Time: 5 mins

A simplified model of a three-sided order. The diner, driver, and restaurant apps hold temporary state. A distributed transactional database coordinates the shared order, assignment, and inventory records.

Figure 1. The client apps hold only temporary, volatile in-memory state. The green frame is the persistent shared state: a transactional database that coordinates the order, assignment, and inventory records across all three sides, so related changes apply together.

One order, three sides

A mobile app holds the state needed to draw its current screen. The order itself must outlast any one app, process, or machine. Uber's fulfillment platform stores that shared state in a distributed database.

Use one transaction to charge the diner, assign a driver, and decrement the restaurant's inventory. The database applies all three changes or none of them. When two drivers try to accept the same order, the database allows one update to finish and rejects the conflicting update.

One diner places one order. A transaction updates the payment, driver assignment, and inventory together. A successful order applies all three changes. A failed order leaves all three unchanged. Competing driver updates cannot both finish successfully.

Figure 2. One transaction updates the payment, driver assignment, and inventory together. A successful order applies all three changes. A failed order leaves all three unchanged. Competing driver updates cannot both finish successfully.

Shared state across many machines

Uber reports that its Fulfillment platform handles billions of database transactions per day. It uses Google's Cloud Spanner, a distributed SQL database, to keep related fulfillment records consistent across many machines.

The applications ask for changes. The database stores the shared result. That separation lets a diner, driver, and restaurant see one order without trusting any single phone to hold the authoritative copy.

The disconnected edge

The driver app saves an unfinished action and its latest state to disk when the phone loses its connection. The app sends queued actions to the server after reconnecting and corrects its local state if the server returns a different result.

Figure 3. The driver app saves unfinished actions to disk so they survive an app restart. It sends the queued actions after reconnecting and updates its local state to match the server.

A driver in a parking garage or a dead zone still needs to mark a pickup, complete a delivery, or update a status. Uber calls its solution Optimistic Mode. The app saves the action and its latest state to disk, updates the screen immediately, and sends the action to the server when the connection returns.

  • Save the action. The phone writes unfinished actions to disk so they survive an app restart.

  • Keep the workflow moving. The app shows the expected result without waiting for the network.

  • Send it later. When the connection returns, the app sends queued actions to the server.

  • Correct disagreements. If the server returns a different result, the app updates its local state.

Takeaway: Distributed transactions coordinate shared fulfillment state at Uber's scale, while saved actions let the driver app continue through short network failures.


Going deeper

Why Uber moved this work into the database

Uber's earlier fulfillment system spread coordination across application code and several storage systems. As delivery flows became more complex, that design became difficult to scale and debug.

Uber moved the shared fulfillment state to Cloud Spanner. The database handles related updates together while distributing the data across many machines.

Optional reading: the published systems