SLIDE 12: Section Intro, Capacity Estimation
Section 3: Capacity Estimation

Capacity estimation is where you turn a vague sense of “this needs to be fast” into concrete numbers that drive every architecture decision in your design. In a ride-sharing system, the numbers are not obvious. The dominant data flow is not ride requests. It is GPS location updates, and that single realization changes the entire system architecture.
This section is typically 2-3 minutes of your interview. Every number you estimate should motivate a specific architecture decision. If a number does not lead to a decision, it does not belong in your estimation.
What We’ll Cover
- Why capacity estimation drives architecture, not the other way around
- Traffic estimates: ride requests per second and GPS updates per second
- Concurrent active rides and peak-to-average ratios
- Read-to-write ratio and its implications for the spatial index
- Storage and bandwidth estimates
- Connecting every number to a specific architecture decision
- Worked example: sizing a city-scale location service
Where Capacity Estimation Feeds Into Later Sections
SLIDE 13: Why Capacity Estimation Drives Architecture
The purpose of capacity estimation in an interview is not to show that you can multiply large numbers. It is to demonstrate that you understand which numbers matter and how they shape your design.
A common mistake is spending 10 minutes calculating precise byte-level storage, then never referencing those numbers again. That is wasted interview time. Every number you estimate should point directly to an architecture decision. If you estimate something and never use it, cut it.
The Mapping: Every Number Has a Destination

Interview Tip:
State your numbers, then immediately say what they mean for the design. For example: “At 1.25 million GPS updates per second, scanning all drivers on every ride request is not feasible. This is why we need a spatial index.” That single sentence shows the interviewer you understand the connection between scale and architecture. Numbers without decisions are just arithmetic.
SLIDE 14: Traffic Estimates: Ride Requests Per Second
Starting Point: Daily Ride Volume
Uber processes approximately 20 million rides per day globally. This is our baseline number.
Daily rides: 20,000,000
Seconds per day: 86,400 ≈ 100,000 (rounded for interview math)
Average requests/sec: 20M / 100K = 200/sec
Actual (86,400): 20M / 86,400 ≈ 230/sec
Peak (2-3x average): ~500-700 requests/sec
Interview Tip:
Rounding 86,400 to 100,000 is standard practice in system design interviews. It simplifies the math, and the difference (a ~15% overestimate) is well within the margin of error for capacity planning. Interviewers expect and appreciate this shortcut.
What Each Ride Request Triggers
A single ride request is not a single operation. It fans out into a chain of service calls:
At 250 requests/sec, each triggering 5+ downstream operations, the system processes roughly 1,250+ internal operations per second for ride requests alone.
This sounds significant. But it is not the bottleneck. The next slide reveals what is.
SLIDE 14B: Traffic Estimates: GPS Updates Per Second
The Number That Changes Everything
Active drivers at any time: 5,000,000
GPS update interval: every 4 seconds
GPS updates per second: 5,000,000 / 4 = 1,250,000/sec
1.25 million writes per second. This is 5,000 times the ride request volume.

Why This Is the Real Engineering Challenge
Ride requests are the user-facing flow, and they matter. But the GPS update stream is the engineering problem that defines the architecture. Every one of those 1.25 million updates per second must:
- Arrive at the Location Service via a persistent WebSocket connection
- Update the driver’s position in the spatial index (Redis GEOADD or in-memory quadtree)
- Potentially trigger a cell boundary change in the geohash or quadtree structure
- Write to location history asynchronously for analytics and trip reconstruction
Scale Comparison: Why This Eliminates Relational Databases
PostgreSQL max writes: ~50,000/sec (optimistic, well-tuned)
Required write throughput: 1,250,000/sec
PostgreSQL instances: 1,250,000 / 50,000 = 25 instances minimum
Redis GEOADD throughput: ~500,000/sec per instance
Redis instances: 1,250,000 / 500,000 ≈ 3 instances
At 1.25 million writes per second, PostgreSQL is not a viable option for real-time positions. Redis (or an in-memory quadtree) handles this volume comfortably with a fraction of the infrastructure.
This is the single most important number in the entire capacity estimation. It is the reason Section 6 (Geospatial Systems) exists as the largest section in this course.
SLIDE 15: Concurrent Active Rides and Peak-to-Average Ratios
Global Concurrency
20M rides/day, average trip duration: ~20 minutes
Concurrent rides = 20M x (20 min / 1,440 min per day)
= 20M x 0.014
≈ 280,000 average concurrent rides
Peak (2-3x): ~600K-900K concurrent rides globally
Absolute peak (holidays, major events): 2-3M concurrent rides
Each concurrent ride consumes active resources: a trip record in “in_progress” state, WebSocket connections to both rider and driver, continuous ETA recalculation every 30-60 seconds, and real-time position rendering on the rider’s map screen.
Peak-to-Average Ratios by Scope
The global ratio is manageable with standard horizontal scaling. The city ratio requires thoughtful capacity planning. The local ratio is the engineering problem that most candidates miss entirely.
The Concert Problem

A stadium concert ends at 10 PM. 40,000 people leave within 20 minutes. 2,000 of them request rides in the first 5 minutes, all from within a 2-kilometer radius. There are 500 available drivers in that area.
The system as a whole has plenty of capacity. This is not a global scaling problem. It is a localized demand spike where one geographic zone receives 10-80x its normal volume while the rest of the city is quiet. This pattern drives three design decisions covered later:
- Geographic partitioning for independent scaling per region (Section 11)
- Surge pricing to balance supply and demand in the affected zone (Section 10)
- Batch matching during high-demand windows to optimize driver assignment globally (Section 7)
SLIDE 16: Read-to-Write Ratio
In most web applications, you estimate a single read-to-write ratio for the whole system (Instagram is roughly 100:1 reads to writes). In a ride-sharing platform, the read and write patterns are fundamentally different from each other, and both are high-volume.
Writes: Steady, High-Volume GPS Stream
1.25M GPS updates/sec, sustained 24/7
Pattern: constant stream, evenly distributed across all active drivers
Each write: update one driver's position in the spatial index (~100 bytes)
This is a continuous, predictable write load. It does not spike dramatically because the number of active drivers changes gradually, not suddenly.
Reads: Bursty Ride-Triggered Nearby Queries
250 ride requests/sec average, 700/sec peak
Each request triggers a nearby-driver query against the spatial index
Each query scans 9 geohash cells (target + 8 neighbors) and returns 10-50 candidates
Reads spike with ride request volume. During the concert problem (2,000 requests in 5 minutes from 2km), the same small set of spatial index cells gets hammered with concentrated read traffic.
Why This Matters for Architecture
The write path and read path must be separated. If reads and writes contend on the same data structure with the same locks, 1.25M writes/sec will starve the read queries during peak demand, or peak read queries will block GPS updates from landing.

Redis handles this naturally: GEOADD writes and GEOSEARCH reads do not block each other due to Redis’s single-threaded event loop processing commands sequentially with sub-microsecond operations. For an in-memory quadtree, you would need explicit read-write lock separation or a copy-on-write strategy.
SLIDE 17: Storage Estimates
Storage estimation reveals which data types dominate your infrastructure and which database technologies you need. In a ride-sharing system, the answer is not trips. It is location history, by a factor of 250x.
Trip Records
20M rides/day x 2 KB per trip record = 40 GB/day
40 GB/day x 365 = ~15 TB/year
Content: trip_id, rider_id, driver_id, pickup/dropoff locations,
timestamps, fare, surge multiplier, payment reference,
state transitions
15 TB/year is large but manageable in a sharded PostgreSQL deployment. Trip records are written once (at trip creation), updated a few times (state transitions), and read occasionally (trip history, analytics). This is a standard relational workload.
Location History
1.25M GPS updates/sec x 100 bytes per record = 125 MB/sec
125 MB/sec x 86,400 sec/day = 10.8 TB/day
10.8 TB/day x 365 = ~3.9 PB/year
3.9 petabytes per year. This is 250 times the trip record volume. Location history is written at extreme throughput (1.25M records/sec), rarely read in real time (primarily used for trip reconstruction, analytics, and ML training), and accessed in time-range patterns (“show me all positions for trip X between 2:15 and 2:35 PM”).
The Storage Insight
Location history needs a time-series database (TimescaleDB, InfluxDB, or Cassandra) optimized for high write throughput and time-range queries. Storing it in PostgreSQL would require hundreds of instances and would still deliver poor query performance for time-range scans.
SLIDE 18: Bandwidth: WebSocket Persistent Connections
The Connection Model
A ride-sharing platform maintains persistent WebSocket connections with every active driver. This is fundamentally different from the HTTP request-response model used by content platforms like Instagram or YouTube.
Concurrent WebSocket connections: 5,000,000
Upstream data per connection: ~100 bytes every 4 seconds (GPS coordinates + metadata)
Total upstream bandwidth: 5M x 100 bytes / 4 sec = 125 MB/sec sustained
125 megabytes per second of sustained upstream traffic, arriving continuously across 5 million persistent connections.

Why This Requires a Dedicated WebSocket Gateway
An API Gateway optimized for short-lived HTTP requests will exhaust memory and file descriptors long before reaching 5 million persistent connections. The WebSocket Gateway is a separate service with its own scaling and deployment strategy.
This is the architectural insight from Section 2 (Requirements) materializing as a concrete infrastructure decision. It carries directly into Section 4 (Architecture) where we design the entry layer.
Downstream Push Bandwidth
The WebSocket connection is bidirectional. The system also pushes data downstream to drivers and riders:
Dispatch offers to drivers: ~500 bytes per offer, ~250/sec = 125 KB/sec
ETA updates to riders: ~200 bytes per update, ~280K active rides x 1 update/30 sec
= ~9,300 updates/sec = ~1.9 MB/sec
Location updates to riders: ~100 bytes per update, ~280K active rides x 1 update/sec
= ~28 MB/sec
Downstream bandwidth (~30 MB/sec) is smaller than upstream (125 MB/sec) because only riders in active rides receive updates, while all 5 million active drivers continuously send GPS data.
SLIDE 19: Connecting Estimates to Architecture Decisions
This is the summary slide that ties every number from this section to its destination in the course. If you take away one thing from capacity estimation, it is this table.
The Complete Mapping
The Three Numbers That Matter Most
If you are short on time in an interview, these are the three numbers worth stating:
Everything else (ride requests per second, trip storage, payment volume) is important for completeness but does not fundamentally change the architecture the way these three do.
Interview Tip:
After stating your estimates, use this transition to move into architecture: “These numbers tell us three things. First, we need a spatial index that handles over a million writes per second. Second, location history needs a time-series database, not PostgreSQL. Third, 5 million persistent WebSocket connections require a dedicated gateway separate from our API gateway. Let me draw the architecture that addresses these constraints.”
That transition takes 15 seconds and shows the interviewer that your estimates drove your design decisions.
SLIDE 20: Worked Example: Sizing a City-Scale Location Service
This worked example takes the global estimates and narrows them to a single city to show how the numbers translate into concrete infrastructure decisions.
Given Values
City: Mumbai
Active drivers: 50,000
GPS update interval: every 4 seconds
Query latency target: sub-200ms for nearby driver lookups
Trip volume: ~500,000 rides/day in this city
Step 1: Write Throughput
50,000 drivers / 4 seconds = 12,500 GPS writes/sec
Redis GEOADD benchmark: ~500,000 operations/sec per instance
Utilization: 12,500 / 500,000 = 2.5%
Result: a single Redis instance handles this city comfortably.
Step 2: Memory Footprint
Each driver position: ~50 bytes (driver_id + lat + lng + timestamp)
50,000 drivers x 50 bytes = 2.5 MB
Redis instance memory: typically 1-16 GB available
Utilization: 2.5 MB / 1 GB = 0.25%
Result: memory is not the constraint. Write throughput is the limiting factor.
Step 3: Location History Volume
12,500 writes/sec x 100 bytes per record = 1.25 MB/sec
1.25 MB/sec x 86,400 sec/day = 108 GB/day
108 GB/day x 365 = ~39 TB/year for this one city
Step 4: Nearby Query Performance
Ride requests in Mumbai: ~500K/day ÷ 86,400 ≈ 6 requests/sec average
Peak (4x): ~24 requests/sec
Each query: GEOSEARCH within 5km radius, return top 10 drivers
Redis GEOSEARCH latency: sub-millisecond for 50K entries
Result: query latency is well under the 200ms target.
Architecture Decision for This City

A single Redis instance with GEOADD and GEOSEARCH handles both the write load and the read queries for a city of this size. Location history flows asynchronously to a time-series database. The bottleneck at this scale is write throughput (2.5% utilization), not memory (0.25% utilization) and not query latency (sub-millisecond).
For a mega-city (500K drivers), you would need Redis Cluster or geographic sub-partitioning within the city. But for most cities globally, a single Redis instance per city is sufficient, which makes the geographic partitioning strategy (Section 11) straightforward: one Redis instance per city, independent scaling.
SLIDE 21: Wrong vs Right: Capacity Estimation
Mistake 1: Spending Too Long on Math
Wrong: “Let me calculate the exact number of bytes per trip record. The rider_id is a UUID which is 16 bytes, the driver_id is another 16 bytes, the status enum is 1 byte…” (continues for 10 minutes)
Better: “A trip record is roughly 2 KB. At 20 million rides per day, that is 40 GB of trip data per day, about 15 TB per year. That is manageable in sharded PostgreSQL. The real storage challenge is location history at 10 TB per day, which needs a time-series database.”
Why it matters: Interviewers allocate 2-3 minutes for estimation. Spending 10 minutes on byte-level precision signals that you cannot distinguish important details from irrelevant ones.
Mistake 2: Estimating Only Ride Requests
Wrong: “We have 20 million rides per day, so about 250 requests per second. We will need a few servers to handle that.”
Better: “Ride requests are 250 per second, which is moderate. But each of our 5 million active drivers sends a GPS update every 4 seconds, which is 1.25 million writes per second. That is 5,000 times the ride request volume, and it is the number that drives our spatial index design.”
Why it matters: Identifying the GPS update stream as the dominant data flow is the key insight of this section. It separates candidates who understand the system from those who see only the user-facing flow.
Mistake 3: Numbers Without Decisions
Wrong: “We will need 10 TB of storage per day for location data.” (then moves on to architecture without connecting this number to anything)
Better: “10 TB per day of location writes means PostgreSQL is not viable for this data. We need a time-series database like TimescaleDB or Cassandra that is optimized for sustained high-throughput sequential writes and time-range queries.”
Why it matters: The interviewer wants to see that your estimates influence your design. A number that floats without a consequence is a number that should not have been estimated.
SLIDE 22: Interview Practice: Capacity Estimation Pacing
Time Budget: 2-3 Minutes Maximum
Capacity estimation is a supporting section, not the main event. Spend 2-3 minutes, then transition into architecture. If the interviewer wants more depth, they will ask.
Recommended Flow
Minute 1: State baseline numbers
"Uber handles about 20 million rides per day. That is roughly 250
requests per second average, 500-700 at peak."
Minute 2: Reveal the dominant data pattern
"The bigger number is GPS. 5 million active drivers sending updates
every 4 seconds gives us 1.25 million writes per second. That is
5,000x the ride request volume. This drives our spatial index choice."
Minute 3: Connect to architecture decisions
"Location history alone is 10 TB per day, so we need a time-series
database. And 5 million concurrent WebSocket connections require a
dedicated gateway. These three numbers shape the architecture I am
about to draw."
The Transition Sentence
This is the bridge from estimation to architecture. Deliver it cleanly:
“These numbers tell us we need a spatial index handling 1 million+ writes per second, a time-series database for 10 terabytes of daily location data, and a dedicated WebSocket gateway for 5 million persistent connections. Let me draw the architecture that addresses these constraints.”
That transition takes about 15 seconds and sets up everything in Section 4 (Architecture). The interviewer now expects to see a spatial index, a time-series database, and a WebSocket gateway appear in your diagram. You have created a contract with your own estimates, and delivering on it demonstrates structured thinking.
SLIDE 23: Section Cheat Sheet
Key Numbers to Remember
Rides per day: 20M
Ride requests per second: 250 avg, 700 peak
GPS updates per second: 1.25M (the dominant number)
Concurrent WebSocket conns: 5M
Concurrent active rides: 280K avg, 2-3M peak
Trip storage per day: 40 GB (15 TB/year)
Location history per day: 10 TB (3.6 PB/year)
Upstream bandwidth: 125 MB/sec (GPS data)
Peak-to-average (global): 2-3x
Peak-to-average (local): 10-80x (the concert problem)
Number-to-Decision Summary
Common Interview Mistakes
How This Connects to Other Sections
Section 4 (Architecture) builds the component diagram these numbers justify. Section 6 (Geospatial) designs the spatial index that 1.25M GPS writes/sec demands. Section 8 (Database Design) selects technologies matched to each data type and volume. Section 10 (Dynamic Pricing) addresses the concert problem with per-zone surge computation. Section 11 (Scaling) implements geographic partitioning and autoscaling for the peak-to-average ratios calculated here.
Every architectural decision from this point forward traces back to a number estimated in this section.