[PERF] Missing WEB_CONCURRENCY in .env.example leaves Puma in single-process mode, causing request starvation on multi-core servers
Describe the bug
config/puma.rb is configured to support Puma clustered mode:
workers ENV.fetch('WEB_CONCURRENCY', 0)
preload_app!However, WEB_CONCURRENCY is completely omitted from .env.example and default self-hosted environment templates.
Because it is missing from .env.example, almost all self-hosted administrators (across Docker and Linux VM deployments) leave this setting unset. Consequently, Puma defaults to workers = 0 (single-process mode with only 5 threads: RAILS_MAX_THREADS=5).
Under Ruby's Global VM Lock (GVL), any CPU-intensive operations (such as ActiveRecord serialization of message payloads, conversation metadata queries, or Ruby GC cycles taking 200–300ms) block the entire process. When multiple support agents are active or when webhooks (WhatsApp/Facebook/SMS) arrive simultaneously, the 5 threads become fully saturated, and all subsequent web requests queue up in Puma's backlog and time out (504 Gateway Timeout or >3000ms latency), even on servers with 4, 8, or 16 CPU cores.
To Reproduce
- Set up Chatwoot following the standard installation guide using
.env.example. - Notice that
.env.exampleonly specifiesRAILS_MAX_THREADS=5and never defines or mentionsWEB_CONCURRENCY. - Check running processes on a multi-core production server:Only 1 single Puma process is running.
ps aux | grep puma - Under moderate agent activity and incoming webhooks, check request latency or test the
/health_checkendpoint: Requests queue behind long-running ActiveRecord/serialization calls and experience severe latency or timeouts because all 5 threads in the single process are busy.
Expected behavior
.env.exampleshould includeWEB_CONCURRENCYwith clear comments and recommended production sizing (e.g.WEB_CONCURRENCY=2or4depending on available CPU cores and RAM).- The self-hosted deployment documentation should explain Puma Clustered Mode with Copy-on-Write (
preload_app!) to help administrators properly size their instances.
Environment
Linux VM
Cloud Provider
Other [please specify in the description]
Operating system
Ubuntu 22.04 LTS
Proposed Fix
In .env.example (around line 72 next to RAILS_MAX_THREADS), add:
# Specifies the number of Puma worker processes to boot in clustered mode.
# On multi-core production systems (>= 4 vCPUs and >= 4GB RAM), setting this to 2-4
# enables clustered mode and prevents Ruby GVL thread starvation under concurrent traffic.
# Defaults to 0 (single process) if unset.
# WEB_CONCURRENCY=2Source: chatwoot/chatwoot