`deploy.resources.reservations.cpus` was doing nothing. Outside Swarm, `docker compose up` silently drops it — verified by inspecting a running container, where CpuShares, CpuQuota and CpusetCpus were all unset while `limits.cpus` and `reservations.memory` came through as NanoCpus and MemoryReservation. So the comment calling it "the piece that actually protects the database" described a guarantee the box never had. It matters on the CX22 the runbook targets: the ceilings sum to 1.2 + 0.6 + 0.5 = 2.3 on 2 vCPU, so the other services can oversubscribe the machine, and with every container on the default weight Postgres competed on equal footing with two image resizes and an ffmpeg poster. Replaced with `cpu_shares`, which does survive the translation — db 2048, caddy 1024, app 512, frontend 256 — so the weighting only binds when the CPU is actually saturated, which is the moment the database must not lose. The Caddyfile gains a 10s header-read timeout: there was no read timeout anywhere, so a client could hold a connection, a tokio task and a `.tmp` file open indefinitely by sending one byte a minute, and the upload sweeper is keyed on mtime precisely so a live upload never ages out. Body reads stay unbounded — a 500 MB video over cellular legitimately takes minutes, and a body timeout would fail exactly the uploads this product exists to collect. .env.example documents that estimated_guest_count is a live input to the quota divisor rather than the inert setting both it and the runbook previously implied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
12 KiB
12 KiB