Build an App Like Uber

Have you ever wondered how Uber is able to support, satisfy and delight 161 million active users, successfully complete over 11 billion rides per year, and generate over $160 billion in gross bookings per year?

We did, and this is the reason we are working on this blog series to understand and decode how Uber’s backend works and operates. This is part 2 of the blog series to understand Uber’s Domain-Oriented Microservice Architecture (DOMA) and design. If your organization also wants to shift from monolithic to microservices, our digital transformation services can help you.

In terms of scale and operational excellence, Uber’s endeavors to ensure billions of smooth rides annually are simply mind-blowing. The very fact that a significant percentage of Americans are using Uber at least once a month shows how important Uber is for the public transport industry and how mainstream Uber has become in just 16 years of its existence.

By understanding and, more importantly, appreciating Uber’s backend process, and their advanced microservice, we can develop and launch better mobile apps and empower millions of users, all across the world.

In part 1 of this series, we understood why Uber adopted a service-oriented architecture, the relevance of DISCO or Dispatch Optimization, and how Uber is able to match a rider with the driver in the shortest possible time and distance by leveraging the features of Google S2 Library for geo-positioning.

In part 2 of the series, we will decode the entire system design of Uber’s backend process, delve deeper into the various components of the system design and find out what happens when a user requests a driver. We will also learn more about Uber’s Geo-Spatial Design.

Without much ado, let’s dive straight into it!

Uber’s System Design

Uber02s

Here’s the diagram of the system design, of Uber’s backend process, and it shows how Uber is able to connect a rider with the driver, and how a trip is successfully completed, taking into consideration geographic locations and data.

In the diagram, a cab is a supply, and the user is the demand.

Now, every 4 seconds, the cab will share its location data to the KAFKA, a specialized API that manages messages between two entities.

Now, every few seconds, the cab will share its location data to the Edge Gateway, also helps to manage REST API,  to handle messages and between external clients and internal services.

This messaging from the cab to the API is handled via the Web Application Firewall, over to the Load Balancer, and then finally to Apache Kafka topics via the Gateway, and from there, to different servers.

One copy of this call is also shared with the DISCO or Dispatch Optimization so that the latest position and status of the cab are known to it.

Here’s a brief description of the various components:

Web Application Firewall (WAF): This component is mainly used for security and blocking purposes: The system can safely block requests from banned IPs, bots and the regions where Uber is not supported.

Load Balancer: There are mainly three different layers of Load Balancers: Layer 3, Layer 4 and Layer 7.

While Layer 3 receives all the traffic from the approved IPs, Layer 4 is used mainly for DNS-based Load Balancing, and Layer 7 is used for Application-level Load Balancing.

Edge Gateway & Kafka: As shared earlier, the Edge Gateway works as the endpoint for receiving messages from the supply, that is, the cabs. In case there are 5000 cabs operating in the region, then Gateway will receive 5000 location messages from the cabs, every few seconds. Concurrently KAFKA REST API will share these live location messages with the DISCO to keep consistency in the system and dispatch process.

Web Socket: In order to share synchronized messages between any Client and a Server, Web Sockets are deployed. In case it’s a normal HTTP request, then web sockets may not be used, but since Uber is handling all messages between the demand and supply in real-time, Web Sockets are an important part of the system design.

Uber03s

Primarily written in Go (Golang) and Java (chosen for their high concurrency and performance capabilities), Web Socket helps to establish a connection between the Cab application and the server, and the User application and the server.

DISCO Component: This is primarily written in Go for supporting real-time information exchange regarding the dispatching of the nearest cabs for the end-users.

Uber04s

In order to scale DISCO servers and functionalities, Uber app developers have deployed custom distributed sharding and membership protocol,s to make all their servers extremely scalable and productive. In the case of DISCO, these internal protocols use two functionalities:

  • Consistent Hashing (Work Distribution) This function is responsible for load balancing. Instead of overloading one server, consistent hashing ensures that the workload (drivers and location data) is evenly distributed across all available servers.
  • gRPC (Communication) While hashing decides where the data goes, gRPC (Google Remote Procedure Call) is the pipe used to send it there.  It allows servers to communicate with ultra-low latency. In a real-time app like Uber, milliseconds matter; gRPC is significantly faster than standard REST API calls.

TL;DR: Rider Request Flow

StageSystem ComponentAction
1. InitiationWebSocketThe user requests a ride via the app
2. ContextDemand ServiceIdentifies request details (Ride Type, Location, Quantity) and forward it.
3. AllocationSupply ServiceUses the H3 Geospatial Index and User ID to query a specific node.
4. MatchingDISCOActivates to find the nearest cab based on ETA and distance
5. NotificationWebSocketSends the ride offer to the driver If accepted, rider gets a success message.

What Happens When Rider Requests A Cab (Demand-Supply Match)

Here’s an overview of what happens when a user requests a cab to go from point A to point B:

  • The Demand Service requests the Supply Service, filtered by the Geospatial Index (H3).
  • The supply server locates a nearby cab
  • A request is pushed to drivers for allocation.
  • After a period of time, the request is sent to another cab (if the initial request fails)
  • Once matching is completed, the user is notified

Although this entire process seems simple, complex orchestration handles the backend logic within the system design to ensure reliable execution.

Uber05s

This is how it happens:

As soon as the rider or the user fires his/her Uber app and requests a cab, that request lands on the Web Socket, which dispatches it immediately to the Demand Service.

Now, the Demand Service identifies the request context. In this case, since the request is coming from a rider for a ride, Demand Service dispatches the request to the Supply Service, with all the information needed: Which type of ride is requested, how many rides are needed, and the location where this ride is needed.

Armed with this information, the Supply Service requests one of the servers in the server ring to fulfill this request. The Supply Service shares the User ID and H3 Location Index for this purpose.

Based on this information, the DISCO gets activated and tries to match the nearest cab available to the rider (as shared in Part 1 of this series), based on the ETA (expected time of arrival), and the distance from the  rider calculated via routing engines. This precise estimation relies heavily on real-time traffic data processed by sophisticated data analytics services.

Once confirmed, the web socket is again activated, and it sends the message to the cabs, asking if they want to accept this ride request.

Once the driver accepts, the ride is successfully matched, and the rider is notified.

If you are looking for Uber app developers and Rideshare app developers who can develop and launch similar mobile apps with service-based architecture, then we can help you.

We at TechAhead have a 200+ strong team of passionate and talented programmers, developers, designers, system architects, project managers, and business analysts who can understand your specific requirements and help you build an app like Uber using modern stacks like Go, Node.js, and Kubernetes.

Here’s your chance to disrupt the mobile ecosystem with stunningly powerful and aesthetic mobile apps, with unprecedented scalability and features.