Skip to content
Skillpedia
Deploy & cloud (DevOps)48k · #3166

graceful-shutdown

Lets your agent implement safe server shutdowns, ensuring task completion.

What it does

This tool helps computer programs finish their tasks in an organized way. It ensures everything being worked on is completed before shutting down, preventing data loss or abrupt interruptions.

When to use it

  • ✓When updating a program without it needing to suddenly stop working.
  • ✓When a program processing tasks needs to end safely.
  • ✓When using systems that send a signal to shut down the program politely.

Example of what to ask your AI

“How do I make my program shut down safely when it receives a shutdown signal?”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/graceful-shutdown/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/graceful-shutdown/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

The program listens for shutdown signals (like Ctrl+C). Upon receiving one, it stops accepting new tasks, waits for current tasks to finish, and releases resources before exiting.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add sickn33/agentic-awesome-skills --skill graceful-shutdown

Or download just the file:

curl -L https://raw.githubusercontent.com/sickn33/agentic-awesome-skills/main/plugins/agentic-awesome-skills-claude/skills/graceful-shutdown/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

Graceful Shutdown

Overview

A skill for implementing graceful shutdown in servers, workers, and long-running processes. Ensures in-flight requests complete, background jobs finish or checkpoint, database connections close cleanly, and the process exits with a proper status code. Essential for zero-downtime deployments in container orchestrators (Kubernetes, ECS, Docker Compose) and bare-metal process managers (systemd, PM2).

When to Use This Skill

  • Use when building an HTTP server that must not drop active connections during deploys
  • Use when writing a background worker that processes jobs from a queue
  • Use when deploying to Kubernetes, Docker, or any environment that sends SIGTERM before killing
  • Use when the user says "graceful shutdown", "drain connections", "handle SIGTERM", "zero downtime", or "don't kill active requests"
  • Use when implementing health check endpoints (/healthz, /readyz) for orchestrators

How It Works

Step 1: Register signal handlers early

Trap SIGTERM (orchestrator shutdown) and SIGINT (Ctrl+C) at process startup. Set a flag so the application knows it is shutting down.

let isShuttingDown = false;

function onShutdownSignal(signal: string): void {
  if (isShuttingDown) return; // prevent double-shutdown
  isShuttingDown = true;
  console.log(`Received ${signal}, starting graceful shutdown...`);
  shutdown();
}

process.on("SIGTERM", () => onShutdownSignal("SIGTERM"));
process.on("SIGINT", () => onShutdownSignal("SIGINT"));

Step 2: Stop accepting new work

Immediately stop the server from accepting new connections. For HTTP servers, call server.close(). For queue workers, stop polling for new jobs.

async function shutdown(): Promise<void> {
  // 1. Stop accepting new connections
  server.close(() => {
    console.log("Server closed — no new connections accepted");
  });

  // 2. Mark health check as not-ready so load balancers stop routing
  //    (readiness probe returns 503 from this point)
}

Step 3: Drain in-flight work with a deadline

Wait for active requests and background tasks to finish, but enforce a hard deadline so the process never hangs indefinitely.

const DRAIN_TIMEOUT_MS = 25_000; // must be less than orchestrator's terminationGracePeriodSeconds

async function drainAndExit(): Promise<void> {
  const deadline = setTimeout(() => {
    console.error("Drain timeout reached — forcing exit");
    process.exit(1);
  }, DRAIN_TIMEOUT_MS);
  deadline.unref(); // don't keep the event loop alive just for the timer

  try {
    // Wait for active connections to finish
    await waitForActiveConnections();

    // Flush buffered data (logs, metrics, queues)
    await flushBuffers();

    // Close external resource handles
    await closeResources();

    console.log("Graceful shutdown complete");
    process.exit(0);
  } catch (err) {
    console.error("Error during shutdown:", err);
    process.exit(1);
  }
}

Step 4: Implement readiness and liveness probes

Orchestrators use these to decide whether to route traffic and whether to restart the container. Liveness proves the process is alive; readiness controls whether traffic is routed. While the listener is still available during a drain, keep liveness healthy and return 503 only from readiness. After the listener closes, new probes cannot connect, so do not promise that HTTP liveness remains reachable for the entire termination window.

import { createServer, IncomingMessage, ServerResponse } from "node:http";

function handleHealthCheck(req: IncomingMessage, res: ServerResponse): void {
  if (req.url === "/healthz") {
    // Keep liveness distinct from readiness while the listener is available.
    // Drain-rejection middleware must not turn this endpoint into a 503.
    res.writeHead(200).end("ok");
    return;
  }

  if (req.url === "/readyz") {
    // Readiness: 503 during shutdown so the load balancer stops routing.
    if (isShuttingDown) {
      res.writeHead(503).end("shutting down");
    } else {
      res.writeHead(200).end("ready");
    }
    return;
  }
}

Step 5: Track active connections

Maintain a count of in-flight requests so you know when draining is complete. Use a once guard covering both finish and close events so that client disconnects (aborted requests) correctly decrement the counter.

let activeConnections = 0;
let drainResolve: (() => void) | null = null;


…
FAQ

Why is 'graceful shutdown' important?

To avoid losing data, corrupting files, or interrupting users in the middle of an operation. It ensures a smooth transition, especially in automated systems.

What happens if I don't use this tool?

The program might be terminated abruptly, cutting off connections and leaving tasks unfinished. This can cause errors, data loss, and problems in systems that depend on it.

Does this tool work for any type of program?

Yes, it's designed for servers, background processes (workers), and any program that requires a controlled and safe termination.

Details

Original description by the author

Implement graceful shutdown for servers and workers: drain connections, finish in-flight work, release resources, and exit cleanly on SIGTERM/SIGINT.

repo: sickn33/agentic-awesome-skills

Popularity

GitHub stars
48k
Ranking position
#3166
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills