Heroku で Railsアプリをデプロイできたはいいものの、最初からメモリ使用量が100%を超えている…。
2025-07-06T08:22:11.171032+00:00 heroku[web.1]: Error R14 (Memory quota exceeded)
2025-07-06T08:22:33.313297+00:00 heroku[web.1]: Process running mem=531M(102.1%)
この2行が無限に続きます。
公式ドキュメントを読んでみたところ、
アプリケーションが起動するとすぐに R14 エラーをスローし始める場合、過剰な数の Worker を設定していることが原因である可能性があります。WEB_CONCURRENCY環境設定をより低い値に変更することで、これを修正できる場合があります。
とのこと。
私のアプリは起動してすぐにR14が吐き出され始めるので、完全にコレな感じが。
設定を変えてみました。
puma.rb を見てみると…
デフォルトの設定はこんな感じ。
if ENV["RAILS_ENV"] == "production"
require "concurrent-ruby"
worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count })
workers worker_count if worker_count > 1
end
Concurrent.physical_processor_count
(現在のマシンの物理CPUコア数)を取得して、その数をワーカー数とする。
…よくわからないですが、つまり、もし現在のマシンの物理CPUコア数が4だった時、
worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { 4 })
workers worker_count if worker_count > 1
となり、ワーカーが4プロセス起動する。
HerokuのBasicプランでは1つのdynoに514MBしかメモリがないのに、ワーカーを4つ起動すると、4つのワーカーが同時にアプリをメモリ上に持つので、それはもう大変なことに。
ワーカーが1つの時と比べて単純計算で4倍メモリを食います。
Herokuも、こっちはBasicの働きを期待されてるのに、やってられるか!ってなりますよね。
そこで、さっきのデフォルト設定は削除して、ワーカー数を明示しました。
# これを追加
workers Integer(ENV.fetch("WEB_CONCURRENCY", 1))
これで、どんな時でもワーカー数は1です。
物理CPUコア数が4だからHerokuでも4つワーカー起動しちゃおうとはなりません。
Herokuの環境変数も設定しておきます。
$ heroku config:set WEB_CONCURRENCY=1
これで…
やったー!Herokuの悪態が聞こえてきそうな102.2%から、28.3%までメモリ使用が減りました。感動的。
ひとまずはアプリ存続のチャンスが増大したようです。めでたし。