From 003dfe2d06a4e0f7c8e3f05940cad66358fe18c1 Mon Sep 17 00:00:00 2001 From: Spinnich Date: Mon, 7 Sep 2026 16:43:43 +0000 Subject: [PATCH 1/3] docs(env): replace the WEB_SERVER_CONCURRENCY worker heuristic "2 x CPU cores + 1" is gunicorn's guidance for sync workers. RomM runs UvicornWorker with sync endpoints served from Starlette's threadpool, so the rule does not transfer: on a 16-core host it measured 3x slower than 4 workers and cost 5.31 GB PSS. The variable also only reaches the gunicorn API server; background tasks run in the separate RQ worker processes. Co-Authored-By: Claude Opus 5 --- env.template | 2 +- examples/docker-compose.example.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/env.template b/env.template index 3c9609a183..69ed0ef823 100644 --- a/env.template +++ b/env.template @@ -130,7 +130,7 @@ FORCE_COLOR=false # Force colored log output NO_COLOR=false # Disable colored log output # Web Server -WEB_SERVER_CONCURRENCY=1 # Number of worker processes (recommended: 2 × CPU cores + 1) +WEB_SERVER_CONCURRENCY=4 # Number of API worker processes, not background tasks; ~160MB RAM each, raise only for several concurrent users WEB_SERVER_TIMEOUT=300 # Timeout for web server requests in seconds WEB_SERVER_KEEPALIVE=2 # Keep-Alive connection wait time in seconds WEB_SERVER_MAX_REQUESTS=1000 # Maximum requests a worker processes before restarting diff --git a/examples/docker-compose.example.yml b/examples/docker-compose.example.yml index 67f20f40a9..3b765abdaf 100644 --- a/examples/docker-compose.example.yml +++ b/examples/docker-compose.example.yml @@ -20,7 +20,7 @@ services: - STEAMGRIDDB_API_KEY= # https://docs.romm.app/latest/Getting-Started/Metadata-Providers/#steamgriddb - HASHEOUS_API_ENABLED=true # https://docs.romm.app/latest/Getting-Started/Metadata-Providers/#hasheous - SCAN_WORKERS=2 # How many items you want scanned at once, we recommend 1 worker per CPU. - - WEB_SERVER_CONCURRENCY=3 # How many workers you want available for API calls and tasks we recommend 2 x CPU + 1 + - WEB_SERVER_CONCURRENCY=4 # Workers for API calls, not background tasks. ~160MB RAM each, raise only for several concurrent users volumes: - romm_resources:/romm/resources # Resources fetched from IGDB (covers, screenshots, etc.) - romm_redis_data:/redis-data # Cached data for background tasks From 424d1ebc1ccec492af560866626c0cb4601cf603 Mon Sep 17 00:00:00 2001 From: Spinnich Date: Mon, 7 Sep 2026 16:56:48 +0000 Subject: [PATCH 2/3] fix(server): default to 4 API workers instead of 1 A single worker was the reason a lone user loading a gallery measured 6.474 s worst-case TTFB against 1.939 s at 4 workers. The multi-worker path is already supported: the log forwarder takes a Redis lock so exactly one worker relays. Only installs that never set WEB_SERVER_CONCURRENCY move; any explicit value is preserved. Co-Authored-By: Claude Opus 5 --- docker/init_scripts/init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/init_scripts/init b/docker/init_scripts/init index 1dc1e6340f..9cb824d2c2 100755 --- a/docker/init_scripts/init +++ b/docker/init_scripts/init @@ -138,7 +138,7 @@ start_bin_gunicorn() { --pid=/tmp/gunicorn.pid \ --forwarded-allow-ips="*" \ --worker-class uvicorn_worker.UvicornWorker \ - --workers "${WEB_SERVER_CONCURRENCY:-1}" \ + --workers "${WEB_SERVER_CONCURRENCY:-4}" \ --timeout "${WEB_SERVER_TIMEOUT:-300}" \ --keep-alive "${WEB_SERVER_KEEPALIVE:-2}" \ --max-requests "${WEB_SERVER_MAX_REQUESTS:-1000}" \ From 3767d1b5b9203f96afc1331a6423fa361596634e Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Mon, 7 Sep 2026 14:17:56 -0400 Subject: [PATCH 3/3] cleanup --- env.template | 2 +- examples/docker-compose.example.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/env.template b/env.template index 69ed0ef823..f270116533 100644 --- a/env.template +++ b/env.template @@ -130,7 +130,7 @@ FORCE_COLOR=false # Force colored log output NO_COLOR=false # Disable colored log output # Web Server -WEB_SERVER_CONCURRENCY=4 # Number of API worker processes, not background tasks; ~160MB RAM each, raise only for several concurrent users +WEB_SERVER_CONCURRENCY=4 # Number of API worker processes, raise for several concurrent users WEB_SERVER_TIMEOUT=300 # Timeout for web server requests in seconds WEB_SERVER_KEEPALIVE=2 # Keep-Alive connection wait time in seconds WEB_SERVER_MAX_REQUESTS=1000 # Maximum requests a worker processes before restarting diff --git a/examples/docker-compose.example.yml b/examples/docker-compose.example.yml index 3b765abdaf..03a76772a1 100644 --- a/examples/docker-compose.example.yml +++ b/examples/docker-compose.example.yml @@ -20,7 +20,7 @@ services: - STEAMGRIDDB_API_KEY= # https://docs.romm.app/latest/Getting-Started/Metadata-Providers/#steamgriddb - HASHEOUS_API_ENABLED=true # https://docs.romm.app/latest/Getting-Started/Metadata-Providers/#hasheous - SCAN_WORKERS=2 # How many items you want scanned at once, we recommend 1 worker per CPU. - - WEB_SERVER_CONCURRENCY=4 # Workers for API calls, not background tasks. ~160MB RAM each, raise only for several concurrent users + - WEB_SERVER_CONCURRENCY=4 # Workers for API calls, raise for several concurrent users volumes: - romm_resources:/romm/resources # Resources fetched from IGDB (covers, screenshots, etc.) - romm_redis_data:/redis-data # Cached data for background tasks