I upgraded a bunch of sites to Rails 7.1 recently and the ones deployed on Heroku started to show some massively increased memory usage:
How could my app that was using ~128mb of memory be using four times as much with Rails 7.1? Well, its turns out that there was a change made to the default Puma config to make use of all available cores on the server.
The pertinent line is:
How could my app that was using ~128mb of memory be using four times as much with Rails 7.1? Well, its turns out that there was a change made to the default Puma config to make use of all available cores on the server.
The pertinent line is:
worker_count = ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count }
So - set the worker_count to whatever the WEB_CONCURRENCY env var is set to, and if its not set then set it to the processor count. A Standard-1X Heroku server reports 4 as the physical processor count. So four instances of the app would now run. Not optimal on a 512mb server.
I wasn't comfortable with this and in researching I discovered that Heroku has a SENSIBLE_DEFAULTS config setting which sets the WEB_CONCURRENCY env var. This is explained in this Heroku post.
By setting this config, Heroku sets the WEB_CONCURRENCY env var to something, well, sensible. In the case of a Standard-1X Heroku dyno it is set to 2.
This stabilized the memory usage now at around 270-280mb.
Non-Heroku servers are not immune to this issue. The default config as set in that PR will launch workers for all cores of your server if the WEB_CONCURRENCY env var is not set. So advise you observe what happens to your memory usage before and after an upgrade and make decisions accordingly.