system-design · intermediate

Latency vs Throughput vs Bandwidth

The Central Question

Consider two web service API endpoints running on the CoreLab platform (corelab.com):


An operations monitoring dashboard displaying only average throughput (10,000 req/sec) or average latency (89.6ms) declares both endpoints equally healthy. Yet for customers on Endpoint B, 1 out of every 100 checkouts appears completely broken.

Mistaking completion rates for user waiting times leads to flawed engineering decisions.

This lesson answers one central question: How do single-operation delay (latency), operational completion rate (throughput), and pipe capacity (bandwidth) differ, and how do Little's Law, queueing saturation curves, and percentile metrics (p95/p99) isolate system performance bottlenecks?


Defining the Core Metrics

Engineers evaluate system performance across three distinct operational dimensions:

flowchart TD
  subgraph Single Request Metric
    L["1. Latency: Delay per Operation<br/>e.g. 35 ms wait time"]
  end
  subgraph System Rate Metric
    T["2. Throughput: Completion Frequency<br/>e.g. 10,000 requests/sec"]
  end
  subgraph Network Pipe Metric
    B["3. Bandwidth: Carrying Capacity<br/>e.g. 10 Gbps channel width"]
  end

Figure 1: Distinguishing single-operation delay (Latency), completion frequency (Throughput), and pipe capacity (Bandwidth).

1. Latency (Duration of One Operation)

**Latency** is the total time elapsed from initiating a single discrete request to receiving its complete response, measured in units of time (milliseconds or seconds).

2. Throughput (Completions Per Unit Time)

**Throughput** is the rate of discrete operations successfully completed by a system per unit of time (e.g. requests per second, transactions per minute).

3. Bandwidth (Channel Carrying Capacity)

**Bandwidth** is the maximum raw data transfer capacity of a physical or logical network channel, measured in bits per second (e.g. Megabits per second, Gigabits per second).

Sequential Breakdown of Request Latency

Total user latency is not a monolithic number; it is the sum of discrete, sequential processing stages:

timeline
    title Sequential Breakdown of Single Request Latency (Total: 185ms)
    section Network Transit
        DNS Resolution : 15ms
        TCP Handshake & TLS Setup : 40ms
    section Server Execution
        Queue Wait Time : 80ms
        Application CPU Logic : 10ms
        Database Query Execution : 30ms
    section Response Return
        Network Payload Transit : 10ms

Figure 2: Component breakdown of total end-to-end user latency.

$$\text{Latency}_{\text{total}} = T_{\text{DNS}} + T_{\text{TCP/TLS}} + T_{\text{Queue}} + T_{\text{AppCPU}} + T_{\text{Database}} + T_{\text{Transit}}$$


Bandwidth vs. Latency: The Cargo Ship Analogy

Bandwidth and latency operate independently. High bandwidth does not guarantee low latency.

flowchart TB
  subgraph High Bandwidth / High Latency
    Ship[Cargo Ship with 10,000 Hard Drives] -->|Data Payload: 80 Petabytes| Time1[Transit Duration: 12 Days]
  end
  subgraph Low Bandwidth / Low Latency
    Fiber[Fiber Optic Packet Push] -->|Data Payload: 1 Kilobyte| Time2[Transit Duration: 5 Milliseconds]
  end

Figure 3: Comparing high-bandwidth/high-latency physical transport against low-bandwidth/low-latency fiber signals.

If you fill a cargo ship with thousands of 8 TB NVMe drives and sail across the ocean:


Conversely, a fiber-optic cable transmitting a single 1 KB packet has tiny bandwidth relative to the cargo ship, but delivers its payload in $5\text{ms}$.


Queueing Theory & Saturation: Why Queues Explode Latency

The relationship between system utilization, throughput, and latency is governed by queueing theory.

flowchart LR
  subgraph Load Arrival Rate
    In[Incoming Requests: 950 req/sec]
  end
  subgraph Server Execution
    Worker[Worker Pool: Max 1,000 req/sec]
  end
  subgraph Utilization Impact
    U1["50% Utilization: Queue Empty (Latency ~10ms)"]
    U2["90% Utilization: Queue Saturates (Latency ~90ms)"]
    U3["99% Utilization: Queue Explodes (Latency -> 990ms)"]
  end
  
  In --> Worker

Figure 4: Non-linear latency growth as resource utilization approaches 100%.

1. Little's Law

In any stable queueing system, the average number of active requests in the system ($L$) equals the arrival rate ($\lambda$) multiplied by the average latency per request ($W$):

$$L = \lambda \times W$$

$$L = 1,000 \times 0.2 = 200\text{ concurrent active requests in memory}$$

2. The Saturation Curve ($M/M/1$ Model)

As resource utilization ($U$) approaches 100%, queue waiting time grows non-linearly according to the $M/M/1$ queueing formula:

$$\text{Queue Wait} \approx \frac{U}{1 - U} \times \text{Service Time}$$

Running server pools at 99% CPU utilization forces incoming requests into massive wait queues, causing user latency to explode by 100x while throughput remains completely flat.

Statistical Analysis: Why Averages Lie (Percentiles & Tail Latency)

Evaluating system performance using average (mean) latency creates deceptive metrics.

gantt
    title Latency Distribution Histogram (99 Fast Requests vs 1 Slow Request)
    dateFormat  s
    axisFormat %S
    section 99 Requests (Fast Path)
    Fast Requests (40ms Average) :active, f1, 00, 1s
    section 1 Request (Tail Outlier)
    Lock Contention Wait (5,000ms) :crit, s1, 00, 5s

Figure 5: Visualizing how tail latency outliers distort user experience while remaining obscured by averages.

The Flaw of Averages

Suppose 99 users experience $40\text{ms}$ latency and 1 user experiences $5,000\text{ms}$ ($5\text{ seconds}$) latency:

$$\text{Average Latency} = \frac{(99 \times 40) + 5,000}{100} = \frac{3,960 + 5,000}{100} = 89.6\text{ ms}$$

An average latency of $89.6\text{ms}$ suggests excellent performance. In reality, $1\%$ of users experienced a catastrophic $5\text{-second}$ delay.

Understanding Percentiles (p50, p95, p99)

Percentiles group latency measurements ordered from fastest to slowest:

Complete Worked Example: Go Moving Percentile Latency Calculator

Let's inspect a production Go thread-safe latency recorder for the CoreLab platform (corelab.com) that tracks latency percentiles (p50, p95, p99) in real time.

package main

import (
"fmt"
"sort"
"sync"
"time"
)

type LatencyTracker struct {
mu sync.Mutex
samples []float64 // Stores duration in milliseconds
maxCount int
}

func NewLatencyTracker(maxSamples int) *LatencyTracker {
return &LatencyTracker{
samples: make([]float64, 0, maxSamples),
maxCount: maxSamples,
}
}

func (t *LatencyTracker) Record(duration time.Duration) {
t.mu.Lock()
defer t.mu.Unlock()

ms := float64(duration.Microseconds()) / 1000.0
if len(t.samples) >= t.maxCount {
t.samples = t.samples[1:] // Sliding window drop oldest
}
t.samples = append(t.samples, ms)
}

func (t *LatencyTracker) GetPercentile(p float64) float64 {
t.mu.Lock()
defer t.mu.Unlock()

if len(t.samples) == 0 {
return 0
}

// Copy and sort samples
sorted := make([]float64, len(t.samples))
copy(sorted, t.samples)
sort.Float64s(sorted)

index := int(p / 100.0 * float64(len(sorted)-1))
return sorted[index]
}

func main() {
tracker := NewLatencyTracker(1000)

// Simulate 99 fast requests (10ms to 40ms) and 1 slow request (5000ms)
for i := 0; i < 99; i++ {
tracker.Record(time.Duration(10+i%30) time.Millisecond)
}
tracker.Record(5000
time.Millisecond) // Tail outlier

fmt.Printf("[LATENCY TELEMETRY]\n")
fmt.Printf("p50 (Median): %.2f ms\n", tracker.GetPercentile(50))
fmt.Printf("p95: %.2f ms\n", tracker.GetPercentile(95))
fmt.Printf("p99 (Tail): %.2f ms\n", tracker.GetPercentile(99))
}


Failure Modes and Engineering Mitigations

Failure ScenarioRoot CauseSystem SymptomDetection MetricMitigation Strategy
1. High-Utilization Queue ExplosionRunning compute nodes at 98% CPU to minimize cloud server costs.Latency spikes by 50x; user requests time out while throughput remains flat.CPU utilization $> 95\%$ accompanied by exponential p99 latency growth.Configure auto-scaling target thresholds to maintain CPU utilization between 50% and 60%.
2. Deceptive Average LatencyEvaluating performance using mean latency instead of p95/p99 percentiles.Dashboards show green 60ms average while 2% of users abandon carts due to 8s delays.Divergence between mean latency and p99 percentile metrics.Mandate p95 and p99 percentile metrics on all production dashboards and SLO alerts.
3. Batching Latency DegradationAggressive request batching introduced to maximize worker throughput.Overall throughput increases by 3x, but individual request latency doubles.Elevated p50 latency on interactive API endpoints following batch deploy.Separate interactive API paths from background bulk processing pipelines.
4. Un-bounded Payload BloatAPI endpoints return full database objects (SELECT *) without pagination.Mobile clients on cellular networks experience high latency and connection drops.Response payload size metrics exceed 5 MB per HTTP response.Enforce compulsory API pagination, JSON field filtering, and Brotli compression.

What You Should Remember

  1. Latency, Throughput, and Bandwidth are distinct: Latency is single-operation wait time, throughput is completion frequency, and bandwidth is raw network channel width.
  2. Never rely on Average Latency: Averages hide tail outliers. Evaluate user experience using p95 and p99 percentiles.
  3. Queues explode at high utilization: Running servers near 100% CPU causes queue wait times to grow non-linearly. Maintain headroom buffers (50-60% target utilization).
  4. Little's Law governs active concurrency: $L = \lambda \times W$. Reducing request latency directly decreases concurrent memory load on app servers.
  5. Optimize for product context: Interactive APIs require low latency (p99 $< 200\text{ms}$); background processing pipelines require high throughput.

Glossary of Terms

TermDefinition
LatencyThe total duration elapsed from initiating a single request to receiving its complete response.
ThroughputThe rate of discrete operations or data units processed by a system per unit of time.
BandwidthThe maximum data transfer capacity of a physical or logical network link.
p95 / p99 PercentileStatistical metrics representing the latency boundary under which 95% or 99% of sampled requests fall.
Tail LatencyThe slow minority of requests (top 1% or 0.1%) that experience worst-case delays.
Little's LawThe queueing principle establishing that concurrent items ($L$) equal arrival rate ($\lambda$) times latency ($W$).
SaturationThe operational state where a resource (CPU, memory, disk IOPS) reaches 100% utilization.

Practice Scenario and Self-Assessment

Performance Scenario

An image processing API processes user avatar uploads (`corelab.com`): **Questions**:
  1. Explain why average latency ($120\text{ms}$) fails to reflect the user experience of the 1% tail.
  2. Using queueing theory, explain why worker CPU utilization at 97% is causing the $9.5\text{-second}$ p99 tail latency spike, and propose two architectural changes to reduce p99 latency to $< 500\text{ms}$.

Interactive Self-Assessment

Queue wait time grows non-linearly as resource utilization approaches 100% saturation.

Network bandwidth automatically shrinks when CPU utilization is high.

Average throughput decreases to zero whenever latency increases.

The p50 percentile metric automatically overrides system CPU scheduling.

Average latency obscures severe tail outliers experienced by the slowest 1% of user requests.

p99 latency calculates network bandwidth consumption across all client links.

p99 latency is easier to compute than arithmetic averages on database servers.

p99 latency measures throughput rates rather than user waiting times.


What to Learn Next

Track: Engineering Foundations

Next: Process vs Thread — Isolation and Shared Memory

By Shubham Jain

All articles · Study paths

Shubham Jain · Learning Lab