← All writing
Cloud & Infra·Sep 4, 2026·5 min read

The connection pool that was fine until it wasn't

A pool sized for normal traffic works for months. Then one slow query holds its connection a few seconds too long, and every other request in the app starts queueing behind it.

H

Hammad Iqbal

Software Engineer

Database connection pools are one of those settings you configure once during setup and never think about again — until every request in the app starts timing out at the same moment, the database itself reports client CPU as fine, and the actual bottleneck turns out to be a queue of application processes waiting for a connection that never frees up.

In brief
  • A connection pool that looks correctly sized under normal load can still exhaust under a small number of slow queries.
  • Symptoms show up as request timeouts across unrelated endpoints, not as a database error.
  • Pool size, query timeout, and idle-connection reaping all need to be tuned together, not independently.

One slow query can starve the whole app

A pool of 20 connections handles normal traffic without issue. Then a report-generation endpoint runs a query that takes 8 seconds instead of 80 milliseconds. Multiply that by a handful of concurrent users hitting the same endpoint, and a meaningful fraction of the pool is now tied up on one slow code path — while every unrelated request, including ones that don't touch that table, waits in line for a connection to free up.

Why the symptoms look unrelated

Because the pool is shared across the whole application, exhaustion doesn't announce itself as a database problem. It shows up as timeouts on the login endpoint, the health check, and the checkout flow simultaneously, which sends most people looking at the load balancer or the app server before anyone thinks to check how many connections are currently checked out.

  • Add a connection-pool-usage metric (checked-out vs total) and alert well before it hits 100%
  • Set an explicit statement timeout so one query can't hold a connection indefinitely
  • Separate pools for latency-sensitive request paths and slow background/report queries

Sizing is a tradeoff, not a constant

A bigger pool delays the symptom but doesn't fix the cause, and past a point just moves the bottleneck to the database's own max-connections limit. The fix that actually holds is bounding how long any single query is allowed to occupy a connection, and giving slow, infrequent queries a separate pool so they can't queue out the fast, frequent ones.

Takeaway

If unrelated endpoints start timing out together, check the connection pool before the code — a shared resource turns one slow query into an outage for everyone.

Have a project this kind of thinking applies to?

Tell me what you're building — I read every message myself.

Available for new projects

4+

Years exp.

8+

Projects shipped

<6h

Avg. reply time

Let's build something

Tell me about your project.

Share what you're building, your timeline, and the best way to reach you.