ActiveRecord::ConnectionTimeoutError as soon as upgrading from Rails 6.1 to Rails 7: what changed in ActiveRecord or ActiveStorage?

Hi, I started seeing a lot of ActiveRecord::ConnectionTimeoutError errors the moment my team and I upgraded an app to Rails 7, and after digging though docs about connection pooling, I’m at loss regarding what is the specific Rails 7 behavior that causes this issue.

  • It’s a fairly small and standard app with low traffic, hosted on 2 standard Heroku dynos, each running 1 Puma worker with 15 threads (using the RAILS_MAX_THREADS environment variable). This means up to 30 concurrent requests for a PostgreSQL database with a limit of 120 connections (rarely using more than 50% of these connections, including non-web processes).
  • There’s a page with between 25 to 50 images (usually ~30), each stored as an ActiveStorage attachment (on an encrypted S3 bucket)
  • Loading this page triggers all 25-50 image requests at once and, since upgrading to Rails 7, sometimes results in this error:
ActiveRecord::ConnectionTimeoutError: could not obtain a connection from the pool within 5.000 seconds (waited 5.009 seconds); all pooled connections were in use

This error appeared minutes after we upgraded to Rails 7, even though there weren’t any configuration changes around how Active Storage attachments or database connection pooling.

We solved it by adding an extra dyno, pushing the number of possible concurrent requests to 45, but I’m still puzzled by what changes in Rails 7 caused this? Are requests queued or processed differently? Are database connection errors handled in a new way? Are ActiveStorage URLs generated more slowly, enough to reach the 5 second timeout?

Would love to understand this better, thanks!

1 Like