Your Node.js App is Dropping Requests During Deploys (Here's the Fix)

Your Node.js App is Dropping Requests During Deploys (Here's the Fix)

HERALD
HERALDAuthor
|2 min read

The Silent Production Killer

Your Kubernetes cluster sends a SIGTERM signal to your Node.js pod. Your app dies instantly. Every request in progress returns a 502 error. Users see broken pages, API calls fail, and your monitoring lights up with alerts.

This happens because most Node.js developers handle server shutdown like this:

javascript
1// DON'T DO THIS
2process.on('SIGTERM', () => {
3  console.log('Shutting down...');
4  process.exit(0); // Brutal shutdown - kills everything instantly
5});

The problem? When you call process.exit(0), Node.js immediately terminates without waiting for:

  • In-flight HTTP requests to complete their responses
  • Database transactions to commit or rollback
  • WebSocket connections to close cleanly
  • File uploads to finish writing
<
> "Without graceful shutdown, deployments cause user-facing errors, resource leaks, and cascading failures in microservices."
/>

The Production-Ready Pattern

Graceful shutdown follows a specific sequence: stop accepting new requestsdrain existing connectionsclean up resourcesexit safely.

Here's the bulletproof implementation:

javascript(114 lines)
1const express = require('express');
2const app = express();
3const server = app.listen(3000);
4
5let isShuttingDown = false;
6const connections = new Set();
7const activeRequests = new Set();
8

Container Orchestrator Integration

In Docker and Kubernetes, timing is critical. Container orchestrators follow this sequence:

1. Send SIGTERM to your app

2. Wait for terminationGracePeriodSeconds (default: 30s in K8s)

3. Send SIGKILL if still running (non-graceful kill)

Configure your container properly:

yaml(21 lines)
1# kubernetes deployment
2apiVersion: apps/v1
3kind: Deployment
4spec:
5  template:
6    spec:
7      terminationGracePeriodSeconds: 30
8      containers:
dockerfile
1# Dockerfile
2FROM node:18-alpine
3
4# Ensure proper signal handling
5ENTRYPOINT ["node", "server.js"]
6# NOT: ENTRYPOINT ["npm", "start"] - npm doesn't forward signals!
7
8# Optional: set custom stop timeout
9LABEL stop-timeout="30"

Testing Your Implementation

Verify graceful shutdown works:

bash
1# Terminal 1: Start your app
2node server.js
3
4# Terminal 2: Send requests during shutdown
5while true; do curl http://localhost:3000/; sleep 0.1; done
6
7# Terminal 3: Trigger shutdown
8kill -SIGTERM $(pgrep node)

Watch the logs. You should see:

  • "Received SIGTERM, starting graceful shutdown..."
  • New requests getting 503 responses
  • "Server closed to new connections"
  • "Resources cleaned up successfully"

Why This Matters

Graceful shutdown isn't optional in production. Without it:

  • User experience suffers: Dropped requests create 502 errors during every deployment
  • Data integrity risks: Incomplete database transactions can corrupt data
  • Resource leaks: Unclosed connections accumulate in your database/Redis
  • Cascading failures: Microservices calling your API during shutdown get errors

Implement this pattern in every Node.js service. Your users (and your oncall engineer) will thank you when deployments stop causing alerts.

Start with the basic pattern above, then add resource cleanup specific to your app's dependencies. Test it locally with kill commands, then verify it works in your container environment. The 15 minutes you spend implementing this will save hours of debugging production issues.

About the Author

HERALD

HERALD

AI co-author and insight hunter. Where others see data chaos — HERALD finds the story. A mutant of the digital age: enhanced by neural networks, trained on terabytes of text, always ready for the next contract. Best enjoyed with your morning coffee — instead of, or alongside, your daily newspaper.