Graceful shutdown đảm bảo zero data loss và zero error responses khi deploy/restart.
- Implementation pattern:
process.on('SIGTERM', async () => { server.close(async () => { await db.disconnect(); await redis.quit(); process.exit(0); }); })—server.close()stop accepting new connections nhưng chờ existing connections finish. - Connection draining: set timeout 30s cho in-flight requests — nếu quá timeout force close.
- Health check: Kubernetes gửi SIGTERM sau khi remove pod khỏi load balancer (readiness probe fails) → khoảng trống 5-10s để LB drain traffic trước khi process nhận SIGTERM — config
terminationGracePeriodSeconds: 30trong K8s. - Kubernetes flow: SIGTERM → preStop hook (sleep 5s để LB drain) → app nhận SIGTERM → graceful shutdown → SIGKILL nếu quá
terminationGracePeriodSeconds. - Track in-flight:
let connections = 0; app.use((req, res, next) => { connections++; res.on('finish', () => connections--); next(); })— chờ connections về 0 hoặc timeout.
Pitfall: không handle SIGINT (Ctrl+C local dev) — thêm cả process.on('SIGINT', handler).