DEV Community

loading...

Discussion on: Stumped about Rails Connection Limit Error

Collapse
k776 profile image
Kieran Pilkington

Hey Ethan,

If you setup Rails using the puma option, Rails uses a default thread pool of 5 for puma (config/puma.rb, see max_threads_count), and a connection pool of 5 (config/database.yml, see default->pool). That means effectively that 5 puma threads share 5 database connections.

In some instances, Puma can process more than 5 requests at once (if something is blocked by IO, it can pause that and execute another). So during very busy times (when more than 5 requests are processing at once), if the 5 db connections are all busy with something else (usually because of slow SQL queries), you'll get that error when the puma thread has to wait over 5 seconds for a free DB connection.

The easiest fix is to increase the DB connection pool (usually I'd do three times the amount of puma threads). Alternatively, decrease the max threads in puma from 5 to 3 (this means however that you'll not be able to serve as many requests per second). Since you're on AWS with connection max of at least 100, increasing the DB connection pool to 15 is the better option here.

The other thing to do is optimise your queries. If the app can't get a DB connection for 5 seconds, your database queries are taking way too long and not returning connections to the pool fast enough. You should aim to have your queries returning within 50ms or less usually.

Hope this information helps.

Collapse
xipher7934 profile image
Ethan Author

"In some instances, Puma can process more than 5 requests at once" Whaaaat? So having a max_threads_count of 5 isn't actually a MAX of 5 threads? That's good to know! I've been assuming that I could count on that number.

Collapse
k776 profile image
Kieran Pilkington

It is a max of 5 threads, but not a guaranteed max of 1 request per thread, especially when using different ruby interpreters without a GIL. At least that is what I've seen in my own use of Puma, and I'm sure someone more familiar with Puma could provide a more detailed explanation. The short answer anyway is: keep your DB pool size higher than the puma thread count to avoid potential issues

Also one more thing to keep in mind when using Puma, because it uses threads, you have to be very careful to make your code threadsafe. Code something the wrong way, and you could end up leaking data from one thread to another; i.e. someone could end up seeing someone elses data.

If you're an application that requires absolute assurance of no data leakage (e.g. bank, insurance, health, etc etc), avoid having to worry about threadsafety by switching from Puma threads (1 process, 5 threads each) to Puma workers (5 processes, 1 thread each).