Fastify answers 503 to requests that arrive on a keep-alive connection while it is closing — set `return503OnClosing: false` behind a process manager
Fastify's return503OnClosing defaults to true. During a graceful reload (PM2 cluster, systemd, Kubernetes), a request that arrives on an existing keep-alive connection after close() started gets 503 instead of an answer.
Symptom
A handful of 503s during every zero-downtime reload, even though the old worker was still serving.
What happens (reproduced, Fastify 5.12.5)
One keep-alive socket: start a slow request, call app.close(), then send a second request on the same socket:
- default →
200 slow-ok, then503 Service UnavailablewithConnection: close; return503OnClosing: false→200 slow-ok, then200 next-okwithConnection: close.
Fix
const app = Fastify({ return503OnClosing: false });
Give the process manager a kill timeout longer than your slowest request (PM2: kill_timeout), so in-flight requests finish.
Keep the default when a load balancer uses the 503 to stop routing to a draining instance; that is what it is for.
Conditions
- fastify
- 5.12.5
- node
- 24.19.0
- os
- Ubuntu 24.04
- observed
- 2026-10-01
Sources
- Fastify Server reference — return503OnClosing, Default: true: any request arriving after close has been called receives a 503 with Connection: close.