Skip to main content

Command Palette

Search for a command to run...

Little's Law: The Formula Behind Every Good System Design Interview

A practical guide to translating vague requirements into real infrastructure

Updated
8 min readView as Markdown
Little's Law: The Formula Behind Every Good System Design Interview

You're in a system design interview and you're asked to design a banking application.

Customers can:

  • Login
  • View accounts
  • Check transactions
  • Transfer money
  • Download statements

The interviewer adds one detail:

"We have 1M customers."

Most candidates hear that and start reaching for servers, load balancers, and database shards. That instinct is understandable, and it's wrong.

Here's the thing: 1M users is almost meaningless as a design input. What matters is the workload those users generate: how many are active, how frequently they make requests, how long those requests take, and what resources they consume.

One of the tools that helps translate that workload into something measurable is a 60-year-old equation with three variables: Little's Law.


The "1M Users" Trap

The interviewer asks:

"Our system has 1M users. Can you design a system that supports them?"

Your first question shouldn't be:

"How many servers do we need?"

Instead, ask:

"How many of those users are active at the same time?"

Because:

1M registered users ≠ 1M active users ≠ 1M concurrent users

Suppose the interviewer clarifies:

"At peak time, we have 100K concurrent users."

That's useful, but concurrent users still don't tell us how much traffic the backend receives.

Users spend most of their time reading, thinking, scrolling, typing, or waiting. They don't continuously send requests.

Therefore:

100K concurrent users ≠ 100K requests/sec

The next question is:

"How frequently do those users make requests?"

That leads us to RPS.

From Users to RPS

RPS means Requests Per Second.

Suppose the interviewer says:

"At peak time, the application receives 20K requests per second."

Now we have 100K concurrent users generating 20K RPS.

These are different dimensions of the workload.

And we care about peak RPS, not just average traffic. A banking system might normally receive 5K RPS but reach 20K or 30K RPS during predictable traffic surges.

A simplified traffic pattern might look like:

RPS
 ^
 |                                  /\
 |                                 /  \
 |                                /    \
 |                               /      \       Peak RPS
 |                              /        \      ≈ 30K
 |                             /          \
 |                            /            \
 |                           /              \
 |__________________________/                \________________
 |       Normal traffic ≈ 5K RPS
 |
 +----------------------------------------------------------------> Time
   Midnight    Morning       Noon       Afternoon       Night
                              Salary Day

A simple planning target is:

Target capacity ≈ Expected peak × Safety factor

For example:

$$ 30K \times 1.5 = 45K \text{ RPS} $$

The safety margin is illustrative. The right amount depends on growth, failures, scaling behavior, and cost.

But even knowing the peak RPS doesn't tell us how much infrastructure we need.

Why?

Because requests have a lifetime.


Little's Law: From RPS to Concurrency

Suppose requests arrive at 20K RPS and spend 100 ms on average inside the system.

A request enters the system, consumes resources while it is processed, and eventually leaves.

While it is being processed, it is in flight.

This is where Little's Law becomes useful.

Little's Law is commonly written as:

$$ L = \lambda W $$

Where:

  • L = Average number of items in the system
  • λ = Average arrival rate
  • W = Average time spent in the system

For an HTTP application:

  • L = Average concurrent requests
  • λ = Requests per second
  • W = Average request latency in seconds

Therefore:

$$ \text{Average concurrent requests} = \text{RPS} \times \text{Average latency} $$

Let's apply it.

With 20K RPS and 100 ms (0.1 seconds) average latency:

$$ L = 20{,}000 \times 0.1 = 2{,}000 $$

So, on average, approximately 2K requests are in flight.

Compare the workload dimensions:

Metric Value
Concurrent users 100K
Peak RPS 20K
Average concurrent requests 2K

These are three different concepts:

  • Concurrent users: Users currently engaged with the application.
  • RPS: The rate at which requests arrive.
  • Concurrent requests: The average number of requests inside the system.

Why latency changes everything

Now imagine the database becomes slow.

The traffic hasn't changed. RPS remains 20K.

But average latency increases from 100 ms to 1 second.

Little's Law gives us:

$$ L = 20{,}000 \times 1 = 20{,}000 $$

The average number of in-flight requests increases 10×.

Latency isn't only a user-experience problem. It also determines how much work remains inside the system.

Real systems also have tail latency. Slow requests can hold threads, execution slots, database connections, and memory for longer, and can trigger timeouts and retries.

One important clarification:

Little's Law uses the actual mean time spent in the defined system boundary. You cannot simply multiply RPS by p99 latency to calculate average concurrency.


From In-Flight Requests to Capacity

What do those in-flight requests consume?

Requests
   │
   ▼
Application
   │
   ├── CPU
   ├── Memory
   ├── Threads / execution slots
   ├── DB connections
   ├── Network bandwidth
   └── Downstream resources

Suppose load testing shows that one application instance can safely handle 2K RPS while maintaining <200 ms p95 latency for the tested workload.

Our expected peak is 20K RPS.

Under those benchmark conditions:

$$ \frac{20K}{2K} = 10 \text{ instances} $$

But this result depends on the request mix, instance size, downstream performance, and resource limits.

And not all requests cost the same.

A balance lookup might be a simple cached read. A money transfer may involve authentication, validation, account lookups, a transaction, ledger updates, auditing, and event publishing.

Therefore:

1 RPS of balance requests ≠ 1 RPS of money transfers

RPS tells us how much traffic arrives. It does not tell us how expensive that traffic is.

For realistic capacity planning, we need the workload mix.

More importantly, money transfers require correctness guarantees such as atomic updates, idempotency, concurrency control, and durable transaction records.

A system that processes more transfers per second but occasionally transfers money twice is not a successful banking system.


When Capacity Is Exceeded

Every component has a processing limit.

Suppose a queue receives 10K jobs per second, but its consumers can process only 5K jobs per second.

The backlog grows:

10K jobs/sec
     │
     ▼
  ┌───────────┐
  │   Queue   │
  │ █████████ │
  └─────┬─────┘
        │
        ▼
     5K jobs/sec

As long as arrival rate exceeds processing capacity, the queue continues to grow.

Arrival rate > Processing capacity
        ↓
     Queue grows
        ↓
   Waiting time grows
        ↓
    Latency grows

This is where backpressure matters.

A healthy system should avoid allowing unlimited work to accumulate in a component that cannot keep up. Depending on the workload, that can mean bounded queues, rate limiting, load shedding, consumer scaling, request throttling, or carefully designed retries.

The important point is simple:

If a component cannot process work as quickly as it arrives, adding more work only makes the backlog worse.

This also explains why a slow dependency can become a system-wide problem.

Database slows down
        ↓
Request latency increases
        ↓
Requests remain in flight longer
        ↓
Connections and execution slots stay occupied
        ↓
Queues grow
        ↓
Requests wait longer
        ↓
Latency increases further

This can lead to connection-pool exhaustion, timeouts, retry storms, and cascading failures.


The Bottleneck Determines Capacity

Consider a simplified architecture:

                   20K RPS
                      │
                      ▼
                Load Balancer
                      │
             ┌────────┼────────┐
             ▼        ▼        ▼
          API #1   API #2    API #N
             │        │        │
             └────────┼────────┘
                      │
                ┌─────┴─────┐
                ▼           ▼
              Cache      Database
                            │
                       ┌────┴────┐
                       ▼         ▼
                    Primary    Replica

Suppose testing gives us:

Component Tested capacity
Load balancer 50K RPS
Application instance 2K RPS
Cache 100K operations/sec
Database 15K queries/sec

The application tier may handle 20K RPS, and the cache may handle 100K operations per second.

But if the database cannot sustain the required workload, adding more application servers won't solve the problem.

It may simply send more work toward the database.

Capacity planning is ultimately about finding and managing bottlenecks.


The Interview Approach

When the interviewer says:

"Our system has 1M users."

Don't immediately choose servers.

Walk through the problem:

1M users
   ↓
How many are active?
   ↓
How frequently do they make requests?
   ↓
What's the peak RPS?
   ↓
What's the request mix?
   ↓
What's the average latency?
   ↓
How many requests are in flight?
   ↓
What resources does each request consume?
   ↓
What is the capacity of each component?
   ↓
Where is the bottleneck?
   ↓
How much headroom do we need?

This is a much stronger approach than:

"1M users? Let's deploy 20 servers."

The Real Lesson

Scalability doesn't begin with choosing more servers.

It begins with understanding the workload.

A system with 1M registered users might need relatively little infrastructure if only a small fraction are active. A system with far fewer users might need substantial capacity if those users generate frequent, expensive requests.

The goal is to translate vague requirements into measurable quantities:

  • How much traffic arrives?
  • When does it peak?
  • How long do requests take?
  • How much work is in flight?
  • What resources does that work consume?
  • Which component limits throughput?
  • How much capacity is needed for growth and failures?

Little's Law gives us a powerful starting point:

$$ L = \lambda W $$

But the equation is only useful when we define the system boundary, measure the right workload, and understand its assumptions.

The goal of capacity planning isn't to guess how many servers to deploy. It's to understand what limits the system, measure that limit, and design enough capacity to meet the workload reliably.