Engineering Note

Your Rails app can have plenty of CPU and memory and still crash under load.

We saw this happen when traffic increased.

The application servers looked healthy.

But PostgreSQL connections were exhausted.

The problem was the database connection pool.

A Rails app with Puma + Sidekiq can have more concurrent database users than you initially expect.

For example:
Puma: 5 workers × 5 threads = 25 possible DB connections
Sidekiq: 10 concurrent jobs = 10 more connections

That is already 35 potential connections from one server.

Add more application servers and the numbers grow quickly.

The mistake was treating:
pool: 5 as a configuration detail rather than a capacity decision.

We reviewed:
* Puma thread count
* Sidekiq concurrency
* ActiveRecord pool size
* Number of application instances
* PostgreSQL max_connections
* Connection usage during traffic spikes

Then we aligned the pool with actual concurrency instead of increasing it blindly.

The important part:
Increasing the connection pool doesn't automatically increase performance.

At some point, you simply move the bottleneck into PostgreSQL.

Important learning:
Database connections are a finite production resource.

Before scaling your Rails servers, understand how many connections each process can consume and whether your database can handle the combined load.

Scaling Rails isn't just about more servers.

It's about making sure those servers don't fight for the same database resources.