Search across all documentation pages
8 examples to get you started with Resilience for Node.js backends - 6 basic and 2 intermediate.
fetch and AbortSignal.timeout.Hung downstream calls exhaust your connection pool.
const response = await fetch("https://api.partner.com/data", {
signal: AbortSignal.timeout(5_000),
});AbortSignal.timeout available in Node 18+ - no manual setTimeout.TimeoutError to 504 or retry policy upstream.Related: Timeouts Everywhere - full timeout matrix
Do not serve traffic with invalid environment.
import { z } from "zod";
const Env = z.object({
DATABASE_URL: z.string().url(),
PORT: z.coerce.number().default(3000),
});
export const env = Env.parseRelated: Configuration Basics - Zod env parse
Tell Kubernetes whether to restart vs stop sending traffic.
app.get("/health", (_req, res) => res.json({ ok: true }));
app.get("/ready", async (_req, res) => {
try {
await
Related: Observability Basics - probe patterns
Drain in-flight HTTP before exit on deploy.
const server = app.listen(3000);
process.on("SIGTERM", () => {
server.close(() => {
logger.info({ event: "shutdown_complete" });
process.exit(0);
server.close stops accepting new connections; finishes active ones.terminationGracePeriodSeconds.Related: Graceful Degradation - feature-off modes
POST without idempotency keys can double-charge.
async function safeGetWithRetry(url: string, attempts = 3): Promise<Response> {
for (let i = 0; i < attempts; i++) {
try {
const
Related: Retries with Backoff - jitter and idempotency
Users and load balancers need a response within SLA.
app.use((req, res, next) => {
const timer = setTimeout(() => {
if (!res.headersSent) {
res.status(504).json({ error: "Gateway Timeout" });
requestId for correlation.Related: Timeouts Everywhere - server timeouts
Stop calling a failing dependency to let it recover.
let failures = 0;
const THRESHOLD = 5;
let openUntil = 0;
async function callBilling() {
if (Date.now() < openUntil) throw new Error("Circuit open"
opossum library.Related: Circuit Breakers - opossum patterns
One slow vendor cannot consume all sockets.
import { Semaphore } from "async-mutex"; // or custom pool
const vendorSem = new Semaphore(10);
async function callVendor() {
const [, release] = await vendorSem.acquire();
try {
Related: Circuit Breakers - bulkhead with opossum
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.