Merge pull request #1146 from MBombeck/chore/app-memory-default

chore(compose): default the app to 1536m so Node gets a 792 MB heap
This commit is contained in:
Marc-André Bombeck authored and GitHub committed 2026-10-04 17:33:54 +02:00
commit 77fece0fa5
3 files changed
+19 -11

No files matched your search

+6
View File
@@ -499,6 +499,12 @@ API_TOKEN_HMAC_KEY="<openssl rand -hex 32>"
# TRUST_PROXY_HOPS="1"
# TRUST_CF_CONNECTING_IP="1"
# Memory cap of the app container (read by docker-compose.yml, not by the app).
# Node sizes its heap from it: 1536m (the default) gives 792 MB, 1g only 524 MB,
# which a long-used account fills in normal operation. Lower it on a host with
# 2 GB or less, raise it on a busy instance.
# APP_MEMORY_LIMIT="1536m"
# -----------------------------------------------------------------------------
# Outbound requests HealthLog makes on its own -- optional switches
# -----------------------------------------------------------------------------
+10 -8
View File
@@ -467,13 +467,15 @@ services:
options:
max-size: "10m"
max-file: "3"
# Conservative memory ceiling for a small host. HEALTHLOG_PROCESS_TYPE=all
# bundles the AI/rollup worker into this same process, and unbounded that
# workload can grow large enough under load to starve Postgres of memory
# on a shared host. 1g is a starting point, not a measured ceiling — raise
# it with APP_MEMORY_LIMIT in .env if the app gets OOM-killed under real
# load.
mem_limit: "${APP_MEMORY_LIMIT:-1g}"
# Memory ceiling for the app. HEALTHLOG_PROCESS_TYPE=all bundles the
# AI/rollup/backup worker into this same process, and unbounded that
# workload can grow large enough to starve Postgres on a shared host.
# Node sizes its heap from this limit: 1g gives a 524 MB heap, which a
# long-used account fills in normal operation, so garbage collection
# stalls requests for seconds and a weekly backup can crash the process.
# 1536m gives 792 MB. On a host with 2 GB or less, lower it with
# APP_MEMORY_LIMIT in .env; on a busy instance, raise it.
mem_limit: "${APP_MEMORY_LIMIT:-1536m}"
healthcheck:
test:
[
@@ -511,7 +513,7 @@ services:
# options:
# max-size: "10m"
# max-file: "3"
# mem_limit: "${WORKER_MEMORY_LIMIT:-1g}"
# mem_limit: "${WORKER_MEMORY_LIMIT:-1536m}"
db:
# Pinned to the concrete minor instead of the floating `16-alpine`
+3 -3
View File
@@ -210,8 +210,8 @@ let a new model land without one.
This is the part that bites, and it bit the nightly job a release after it bit
the weekly one. The job runs inside the app process, so V8's heap limit is the
app's heap limit, and a container capped at 1 GB gives Node a 524 MB old-space
limit by default. A long-lived Next.js server is already holding a large share
app's heap limit. Node sizes it from the container's memory cap: 1 GB gives a
524 MB old-space limit, the compose default of 1536m (since 1.40.1) gives 792 MB. A long-lived Next.js server is already holding a large share
of that before the job starts.
The uploader used to build the whole backup JSON as one string, gzipped
@@ -305,7 +305,7 @@ writer produces the JSON a page at a time, gzips it as it goes and seals each
megabyte of gzip output on its own with AES-256-GCM. Reading it back (restore,
preview, download) takes the pieces one at a time. Nothing on either path holds
the whole copy, so the size of a copy has nothing to do with the app's memory.
Measured on an account of 2.6 million readings in the default 1 GB container,
Measured on an account of 2.6 million readings in a 1 GB container,
with the web server and the worker in one process: the backup took 87 seconds
and stored 97 MB in 96 pieces, the preview 20 seconds, the download of the
1.4 GB file 25 seconds, and the restore 264 seconds, which gave back every