How to pass the Uber mobile system design interview

AAcePrompt Team·August 2, 2026·10 min read
How to pass the Uber mobile system design interview

The Uber mobile system design round is an entirely different beast from standard backend interviews. You aren't mapping out distributed databases, Kafka queues, or load balancers. Instead, you are designing for one of the most hostile engineering environments on earth: a smartphone sitting on a dashboard in the blazing sun, running on a 3G network in a densely populated city, with 15% battery left. Network connections drop randomly. Operating systems ruthlessly kill background processes. Thermal throttling slows the CPU to a crawl. To pass this interview, you need to architect a bulletproof client-side system capable of handling real-time driver tracking, offline telemetry sync, and complex state management—all without melting the user's phone or draining their data plan.

Interviewers at Uber (and similar gig-economy companies like Lyft, DoorDash, or Instacart) are looking for engineers who understand that mobile apps are highly constrained distributed nodes. They want to see you proactively identify edge cases before they happen. A senior candidate doesn't just draw a box labeled 'Network Request' and move on. They explain what happens when that request times out, how the payload is compressed, how the retry mechanism avoids overwhelming the server, and how the UI reflects that transient state to the user.

Structuring Your 45-Minute Interview

Time management is usually where candidates fail. You have roughly 45 minutes to design a massive, complex system. If you spend 20 minutes talking about UI components, you will fail. You need a strict framework to drive the conversation forward. Here is the exact breakdown you should aim for:

  • Requirements & Scope (5 mins): Pin down exactly what you are building. Are we designing the Rider app or the Driver app? (Hint: The Driver app is much harder and more common for senior interviews).
  • API & Data Models (10 mins): Define the exact payloads crossing the network boundary. Define the local storage schema.
  • High-Level Architecture (10 mins): Draw the core components—UI, ViewModels/Interactors, Repository, Network Client, Local Database, and Location Manager.
  • Deep Dives & Bottlenecks (20 mins): This is where you pass or fail. Focus heavily on offline support, battery optimization, network protocols, and background execution.

Defining Mobile-First Constraints

How to pass the Uber mobile system design interview

Before drawing a single box, you need to establish the constraints of your system out loud. This signals to the interviewer that you think like a mobile engineer, not a backend engineer forced to write Swift or Kotlin. You should explicitly list out the functional and non-functional requirements.

  • Functional requirements: The app must track the driver's location in real-time, sync telemetry data when the phone goes offline, update the trip state (e.g., En Route, Arrived, In Trip), and display an accurate map.
  • Battery constraints: GPS hardware is incredibly power-hungry. You must minimize GPS polling frequency and prevent unnecessary CPU wake locks. Waking the cellular radio constantly will drain the battery in hours.
  • Data constraints: Drivers rely on their personal data plans. Keep cellular data usage strictly capped by compressing payloads, batching network requests, and avoiding chatty API calls.
  • Lifecycle constraints: The app must survive OS-level background terminations. If the OS kills the app due to memory pressure while the driver is navigating, it must instantly recover the active trip state upon reopening.

Architecture and State Management

Uber is famous for its RIBs (Router, Interactor, Builder) architecture, which they built to handle massive engineering teams working on a single app with deeply nested states. You do not need to use RIBs in your interview. In fact, unless you know it perfectly, you shouldn't. Stick to a clean, unidirectional data flow architecture like MVVM or MVI.

The key is separating your concerns. Your UI layer should be completely dumb. It simply observes a state stream (via Kotlin StateFlow or Swift Combine) and renders it. The business logic lives in the Domain layer (Interactors/Use Cases), and the data fetching lives in the Repository layer. The Repository is the single source of truth. The UI never talks to the network directly. The UI asks the Repository for the current trip state, and the Repository decides whether to fetch that from the local SQLite database or the remote server.

Real-Time Telemetry and Battery Optimization

The location tracking engine forms the absolute core of the driver app. If you continuously poll the GPS hardware at 1Hz (once per second) at maximum accuracy, you will kill the phone's battery before the driver finishes their shift. Instead, you have to design an adaptive sampling mechanism.

To do this, you dynamically adjust the polling rate based on the driver's current context. If the accelerometer and GPS indicate the driver is cruising down a straight highway at 65 mph, you don't need location updates every second. You can safely drop the sampling rate to every 5 or 10 seconds and interpolate the path on the backend. As they slow down, approach a turn, or near the pickup point, that frequency has to ramp back up to 1Hz to ensure the rider sees accurate ETA data.

You also need to explain how you interact with the OS location services. Don't just say 'I'll get the location.' Specify that you will lean heavily on the OS-level fused location provider (Google Play Services Location API on Android, CoreLocation on iOS). These smart systems combine GPS, Wi-Fi MAC address lookups, and cellular tower triangulation to grab accurate locations while keeping power draw to a bare minimum. You can also mention applying a basic Kalman filter to smooth out GPS jitter, preventing the driver's car from appearing to 'jump' across city blocks on the map.

Tip: Always bring up thermal throttling during mobile interviews. If your app hogs too much CPU for location processing, map rendering, or network serialization, the OS steps in and throttles the CPU. This degrades performance, causes UI frame drops, and can eventually lead to a forced crash. Offload heavy processing to the backend whenever you possibly can.

The Offline Sync Engine (Local-First Design)

Drivers constantly drive through dead zones—tunnels, rural areas, or dense urban canyons blocking cell towers. When that network inevitably drops, losing telemetry data is unacceptable. The backend needs that data to calculate exact payouts, resolve rider disputes, and train ETA machine learning models. The fix here is a rock-solid local storage layer.

Propose a local-first architecture using SQLite (via Room on Android or CoreData/GRDB on iOS). The moment a location event triggers, it does not go to the network. It gets written straight to a local append-only database table. You should explicitly define this table schema for the interviewer:

  • event_id (UUID, Primary Key)
  • timestamp (Epoch milliseconds)
  • latitude (Double)
  • longitude (Double)
  • accuracy_meters (Float)
  • speed_kmh (Float)
  • sync_status (Enum: PENDING, IN_FLIGHT, SYNCED)

Meanwhile, a separate background Sync Manager observes this table. If there is an active network connection, it batches pending events (e.g., 50 at a time) and ships them off to the server. If the phone goes offline, the events sit safely on the disk, and the Sync Manager goes to sleep.

Once a connection returns, the sync manager wakes up. However, you cannot just dump 5,000 queued location events onto the network at once. If every driver exiting a tunnel does this simultaneously, you will DDoS your own backend. You must implement exponential backoff with jitter. If a sync fails, wait 2 seconds, then 4, then 8, up to a maximum cap, adding a random jitter (e.g., +/- 500ms) to spread out the server load.

API Protocols and Network Resiliency

Trying to send high-frequency location updates through standard REST API calls creates massive HTTP header overhead. If you make a new HTTP request every 3 seconds, you are chewing through cellular data and keeping the cellular radio awake constantly. Real-time telemetry demands a persistent connection. If you want to show true seniority in an interview, dive right into the trade-offs between different streaming protocols.

ProtocolData OverheadBidirectionalBest Use Case
REST / HTTPHighNoOne-off configuration fetches, profile updates
WebSocketsLowYesReal-time chat, basic streaming, legacy support
gRPC / ProtobufVery LowYesHigh-frequency telemetry, strict API contracts
Server-Sent EventsLowServer-to-Client OnlyLive ride status updates pushed to the rider

For the Uber driver app, gRPC with Protocol Buffers (Protobuf) is the industry standard. Protobuf is a binary serialization format that is vastly smaller than JSON. When you are sending millions of location pings per day, saving 50 bytes per payload translates to terabytes of bandwidth saved globally. Furthermore, gRPC supports bidirectional streaming out of the box.

You should also mention QUIC (HTTP/3). Mobile networks are notoriously flaky. When a driver moves from a Wi-Fi network to a 3G cell tower, their IP address changes. Standard TCP connections break and require a costly multi-round-trip handshake to re-establish. QUIC operates over UDP and uses connection IDs independent of the IP address. This means the connection survives network switches seamlessly, completely eliminating TCP head-of-line blocking. Uber relies heavily on QUIC for this exact reason.

Handling OS Terminations and Edge Cases

The final hurdle is proving your system won't fall apart under pressure. Both iOS and Android aggressively kill apps that chew up too much background memory. If a driver switches to a heavy music app or a podcast player while navigating, the OS might silently terminate your app.

To counter this, your architecture has to completely decouple the UI from the background location service. On Android, you must use a Foreground Service tied to a persistent, un-swipeable notification. This elevates the app's priority, telling the OS 'Do not kill me unless absolutely necessary.' On iOS, you utilize Background Location updates and the Background Tasks framework, ensuring your location delegate continues receiving callbacks even when the app is suspended.

But what happens if the app crashes or the phone reboots? You have to solve the 'Cold Start during an Active Trip' problem. When the app launches, it cannot wait 5 seconds for a network call to figure out what screen to show. It must read the last known state directly from local storage. If the local database says the driver is IN_TRIP, the app instantly boots into the navigation screen. In the background, it spins up a network request to reconcile the local state with the server state. If the server says the trip was actually canceled while the phone was off, the app gracefully handles the conflict and updates the UI.

Handling Idempotency and Duplicate Requests

In a flaky network environment, the client will often send a request (like 'Accept Trip'), the server will process it successfully, but the network drops before the 200 OK response reaches the phone. The client assumes the request failed and retries. If you aren't careful, the driver just accepted two different trips, or charged the rider twice.

You must implement idempotency keys for all state-mutating network requests. Generate a unique UUID on the client for the specific action. When the client retries the request, it sends the exact same UUID. The backend checks its cache (usually Redis), sees that it already processed this UUID, and simply returns the cached success response without mutating the state a second time. Mentioning idempotency in a mobile interview is a massive signal of seniority.

Frequently asked questions

How much backend knowledge is expected in a mobile system design interview?

You definitely need a solid grasp of API contracts, pagination, data serialization, and basic database concepts. That said, nobody expects you to design complex microservices, Kubernetes clusters, or database shards. Keep your focus locked on the client-server boundary and exactly how the mobile app talks to those backend APIs.

Should I use iOS or Android specific terminology?

Stick to the terminology of your primary platform, whether that's CoreData/Combine for iOS or Room/Flow for Android. Just be ready to break down the underlying concepts—like SQLite or reactive streams—so an interviewer from a different platform background can easily follow your logic.

How do I handle background location tracking restrictions?

Bring up OS-specific constraints like iOS background modes or Android foreground services that use persistent notifications. You'll also want to explain how your app gracefully degrades functionality—or prompts the user with clear rationale—when they deny those crucial background permissions.

Is it better to use WebSockets or gRPC for location streaming?

Both are entirely valid choices, but gRPC is generally preferred for this specific use case. gRPC gives you much smaller payload sizes via Protobufs, which saves precious cellular data and parsing time. On the flip side, WebSockets are significantly easier to debug and enjoy massive legacy support. Discussing the distinct trade-offs of each approach is exactly how you show real engineering depth.

Related comparisons

See AcePrompt in action

Watch how AcePrompt supports a real technical round - structured answers, tuned to your resume, in real time.

Ace your next mobile system design round with real-time AI guidance.

Get started

See pricing →

Keep reading

Uber Mobile System Design Interview Guide