What Happens When 100 Reads Hit the Database

Lab
Easy
Medium
Hard

Pool of only 5 connectionsEasy

Most requests spend their time queued for a connection, not running.

The database server

Connection pool size (per server)5
CPU workers (cores)8
Query time5 ms

≈2–5 ms = indexed lookup · ≈200 ms = full table scan. The pool limits how many requests may talk to the DB at once.

1 / 150/100 done
t = 0 ms
t = 0: 100 read requests arrive. All 100 requests arrive in the same instant (a burst). The pool only has 5 connections per server, so at most 5 DB requests proceed; the rest wait in line.

Where each of the 100 requests is

1 dot = 1 request
Not arrived
still in flight
0
Answered by cache
never reaches the DB
0
Waiting for a connection
queued in the pool
95
Connected, waiting for CPU
holds a connection
0
Running the query
on a DB worker
5
Done
result returned
0
Timed out
gave up waiting
0
Database servers (1: 1 primary)
Primary
Pool
5/5
CPU
5/8
Latency of every request (sorted)
✓ The database copes
median 55 msp95 100 msslowest 100 ms≈ 1000 req/s

Total time to clear the burst: 100 ms.

Learn the theory

What Happens When 100 Reads Hit the Database: how it works

4 min read · Updated

When 100 requests hit your application in the same second, they don't all hit the database at once — and they can't. A real database has limited connections and limited CPU, so requests queue, execute a few at a time, and finish in waves. Understanding where requests wait — the connection pool, the CPU, or nowhere because a cache answered — is the key to diagnosing slow apps and choosing the right fix.

In short

  • Each request needs a connection from a pool; when the pool is empty, requests wait in line (and may time out).
  • A connection holder still needs a CPU worker to run the query; with few cores, queries run in waves.
  • Total time ≈ (requests ÷ parallelism) × query time. Cut query time, raise parallelism, or send fewer requests.
  • Cache hits never reach the database; replicas multiply read capacity; an index shrinks every query.
  • A pool that is too big just moves the queue from the pool to the CPU — and can make things worse.

The path of one read request

  1. The request reaches an application server thread or event-loop task.
  2. The app may check a cache (Redis, memcached or in-process). A hit returns immediately.
  3. On a miss it asks the connection pool for a database connection. If none is free, it waits.
  4. With a connection, it sends the SQL. The database parses and plans the query, then waits for a free CPU worker/process.
  5. The query reads from the buffer cache (memory) or disk, builds the result and returns it. The connection goes back to the pool.

Connection pools: the first queue

Opening a database connection is expensive (a TCP and auth handshake, plus a server process or thread), so applications keep a pool of reusable connections. If the pool has 10 connections and 100 requests arrive, 10 proceed and 90 queue. If a request waits longer than the pool timeout it fails with errors like “timeout acquiring connection”.

CPU workers: the second queue

Having a connection isn't enough. A database with 4 cores can run about 4 CPU-bound queries at a time, so the rest wait holding their connection. Slow queries make this worse: 100 queries of 200 ms on 4 cores take about 5 seconds, and every waiting query keeps a pool slot occupied — which is how a few slow queries can exhaust the entire pool and take the application down.

Four levers that cope with the load

FixWhat it doesTrade-off
Add an index / fix the queryShrinks every query from hundreds of ms to a few ms — often a 100× win.Slower writes, more disk space.
Cache the readsAnswers repeated reads from memory; only misses hit the database.Staleness, invalidation, extra moving part.
Add read replicasSpreads reads over several servers.Replication lag, stale reads, cost.
Tune pool / add CPUMore parallelism for the same query cost.Limited by hardware; a too-big pool hurts.

Fix the query first (cheapest, biggest), then cache, then replicate, then scale hardware.

Bursts vs steady traffic

The same 100 requests are harmless if they arrive evenly over a second and painful if they arrive in the same millisecond. Spikes (cache expiry, a popular post, a cron job) are what exhaust pools. Defences: queue or rate-limit at the edge, add jitter to cache TTLs, pre-warm caches, and use timeouts and circuit breakers so one slow dependency can't stall everything.

What to monitor

  • Pool wait time and utilization — the earliest warning.
  • Active vs idle connections on the database.
  • p95/p99 query latency, not the average.
  • Slow query log and EXPLAIN (ANALYZE) for the top offenders.
  • Cache hit ratio and replica lag.

Frequently asked questions

What happens when 100 requests hit a database at once?
They compete for a limited number of pooled connections and CPU cores. Some run immediately, the rest wait in the connection pool queue or for a free CPU worker, and finish in waves. If waiting exceeds a timeout, requests fail.
What is a database connection pool?
A set of pre-opened, reusable database connections shared by the application's threads or tasks. It avoids the cost of opening a connection per request and caps how many requests may hit the database simultaneously.
Why do slow queries cause 'connection pool exhausted' errors?
Each running query holds a connection for its entire duration. When queries get slow, connections stay busy longer, the pool empties, and new requests queue until they time out.
How many database connections should I use?
Fewer than most people think. Roughly (cores × 2) plus disk parallelism per database server is a common starting point; beyond that extra connections add contention rather than throughput.
Do read replicas help with write-heavy load?
No. Replicas only serve reads; every write still goes to the primary. They also add replication lag, so very recent writes might not be visible on a replica yet.
Should I cache or add an index first?
Check the query first: an index or a rewrite fixes the root cause for all callers. Caching then removes repeated work, but it can't help the first request or a cache miss.

Keep exploring

More interactive labs

All labs

How Database Indexes Work (B-Tree)

See a B-tree lookup beat a full table scan, and why some queries ignore your index.

Databases12 min · Intermediate

Redis Caching: Cache-Aside, TTL & Eviction

Hit or miss? Watch LRU, LFU, TTLs and a cache stampede decide your database load.

Redis12 min · Intermediate

JS Event Loop Visualizer

See the call stack, microtasks and timers run, frame by frame.

JavaScript10 min · Intermediate

CORS & Preflight Simulator

Edit the request and the server headers, then see exactly why the browser blocks it.

Networking12 min · Intermediate

HTTP Caching Explained

Cache-Control, ETag and 304s, one request at a time.

Networking12 min · Intermediate

What Happens When You Type a URL

DNS, TCP, TLS and HTTP — with a stopwatch.

Networking10 min · Beginner

SQL Isolation Levels Lab

Run two transactions side by side and watch dirty reads, phantoms and write skew appear.

Databases15 min · Advanced

Sharding & Replication

Split data across servers, copy it for reads, and see what each choice costs.

Databases15 min · Advanced

Redis Commands & Data Structures

Strings, lists, hashes, sets and sorted sets, one command at a time.

Redis15 min · Beginner

Webhooks: Delivery, Retries & Signatures

Why you get duplicate deliveries, lost events and forged requests — and how to stop them.

Queues & Jobs12 min · Intermediate

Cron Jobs: Schedules, Overlaps & Missed Runs

Write a cron expression and watch what really happens when jobs overlap or the scheduler is down.

Queues & Jobs10 min · Beginner

Job Queues with BullMQ (Redis)

Watch jobs move through waiting, active, delayed, completed and failed — and see what BullMQ stores in Redis.

Queues & Jobs14 min · Intermediate

RabbitMQ: Exchanges, Queues, Acks & Dead Letters

Direct, topic and fanout routing, competing consumers, prefetch, redelivery and dead-letter queues, drawn.

Queues & Jobs14 min · Intermediate

Git Commands, HEAD & Refs (Visual)

Every core git command drawn with arrows: three areas, commits, branches, HEAD and remotes.

Git15 min · Beginner

Git Merge vs Rebase

Watch the commit graph change under merge, rebase and squash.

Git10 min · Beginner