Rank 3: Container
Environment
- Appwrite 2.5.0, self-hosted via the official docker-compose
- Database adapter: PostgreSQL (
_APP_DB_ADAPTER=postgresql), image postgres 18.3 (Debian 18.3-1.pgdg13+1) - Docker Desktop on macOS (darwin arm64)
What happens
Under a short burst of TablesDB API load (a schema-creation script: ~260 create/list
calls — databases, tables, columns, indexes), PostgreSQL deliberately kills all
backends and runs crash recovery. The API returns 500 general_unknown ("server
closed the connection unexpectedly") for a few seconds until recovery completes.
Root cause
The compose file gives the postgres container this healthcheck:
Test: ["CMD-SHELL", "pg_isready -U user -d appwrite"]
Interval: 5s, Timeout: 5s, Retries: 10
Docker executes the probe inside the container, where postmaster is PID 1, so
postmaster reaps every probe as an untracked child process. When the server is
briefly too busy to answer within pg_isready's default 3s client timeout, the probe
exits with code 2 ("no response") — and postmaster treats any abnormally-exiting
child as possible shared-memory corruption and intentionally restarts everything:
LOG: untracked child process (PID 47216) exited with exit code 2
LOG: terminating any other active server processes
LOG: all server processes terminated; reinitializing
LOG: database system was interrupted; last known up at 2026-10-20 02:01:10 UTC
...
LOG: database system is ready to accept connections
The routine passing probes are visible as untracked child process … exited with exit code 0 every 5 seconds, which confirms the probes are what postmaster is reaping.
So the healthcheck amplifies a load spike into a database restart — it fails
exactly when the server is busiest, and the failure itself takes the server down.