Opening Scenario

Your Django app runs fine with 10 users. You deploy to production and traffic grows to 500 concurrent users. Response times climb from 50ms to 3–4 seconds. CPU is at 10%. Memory is low. Disk I/O is minimal. Your Postgres server isn't breaking a sweat.

You check your application metrics: requests are spending most of their time waiting — not computing or querying. You check Postgres: it reports 490 active connections. Your max_connections is 500. Some requests are failing with FATAL: remaining connection slots are reserved for non-replication superuser connections.

What's happening, and why does adding more app servers make it worse?


Question Progression

Q1: Why is a database connection expensive — and why does opening one per request break at scale?

Question: Your app opens a connection when a request arrives and closes it when the request finishes. That sounds clean and self-contained. Why does this pattern break under load?

In the full tutorial

  • Closing: When to Reach for This

Glossary history

Click dotted jargon to save explanations here.