npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

quiesce

v0.1.4

Published

Ordered, timeboxed graceful shutdown for Node — register named async hooks, drain them LIFO on SIGTERM with per-hook timeouts and a hard deadline.

Readme

quiesce

npm MIT License

Zero-runtime-dependency graceful shutdown for Node.js — register named async hooks, drain them LIFO on SIGTERM with per-hook timeouts and a hard deadline.

The problem

Node.js applications need to shut down gracefully when receiving SIGTERM. Without proper shutdown handling, connections get cut mid-request, in-memory state is lost, and downstream services see cascading failures. The built-in process.on('SIGTERM') works for single cleanup tasks, but coordinating multiple async resources with different timeout requirements requires significant boilerplate.

Managing the shutdown sequence manually introduces common bugs: hooks running in wrong order, slow hooks blocking fast ones, timeout handling scattered across code, and double-signal detection for forced exits. These issues surface in production when deployments time out or processes hang during termination.

Install

npm install quiesce
# or
pnpm add quiesce
# or
yarn add quiesce

Use

import { quiesce } from "quiesce";

quiesce.add("database", async () => await db.close(), { timeout: 5000 });
quiesce.arm();
import { createQuiesce } from "quiesce";
import { createServer } from "http";

const shutdown = createQuiesce();
const server = createServer((req, res) => {
  if (shutdown.isDraining) {
    res.writeHead(503);
    return res.end("Server shutting down");
  }
  res.writeHead(200);
  res.end("OK");
});

server.listen(3000);

shutdown.add("http-server", () => new Promise((resolve) => server.close(() => resolve())));
shutdown.add("redis", () => redis.quit(), { timeout: 2000 });
shutdown.add("database", () => db.close(), { timeout: 5000 });

shutdown.arm({ deadline: 10000, onEvent: (e) => {
  if (e.type === "drain-start") console.log("Shutting down...");
}});

API

createQuiesce(): Quiesce

Creates a new isolated quiesce instance.

quiesce: Quiesce

Default shared quiesce instance.

interface Quiesce

add(name: string, fn: () => unknown, opts?: HookOptions): () => void — Register a named hook. Returns unregister function. LIFO execution. Throws on duplicate name or during drain.

arm(opts?: ArmOptions): void — Install signal handlers. Idempotent. Defaults: signals ["SIGTERM","SIGINT"], deadline 30000ms. Second signal forces exit code 130.

now(reason?: string): Promise<boolean> — Trigger drain programmatically. Returns true if all hooks succeeded. Concurrent-safe.

readonly isDraining: boolean — Whether a drain is in progress.

readonly size: number — Number of registered hooks.

interface HookOptions

timeout?: number — Max wait time for this hook (default: 10000ms). Exceeded hooks become stragglers.

interface ArmOptions

signals?: readonly NodeJS.Signals[] — Signals to listen for (default: ["SIGTERM", "SIGINT"]).

deadline?: number — Total deadline for drain (default: 30000ms). Remaining hooks skipped when reached.

onEvent?: (e: DrainEvent) => void — Observe drain events for logging/monitoring.

exit?: (code: number) => never — Process exit function (default: process.exit). Test seam.

type DrainEvent

{ type: "drain-start"; reason: string } | { type: "hook-start" | "hook-ok"; name: string } | { type: "hook-error"; name: string; error: Error } | { type: "hook-timeout"; name: string; timeout: number } | { type: "drain-end"; ok: boolean; stragglers: string[] }

Non-goals

quiesce will never add built-in support for:

  • HTTP/HTTPS server awareness — compose with server.close() in your hook
  • Health-check endpoints — use your framework's health checks with quiesce.isDraining
  • Cluster/worker coordination — manage worker signaling separately
  • Configuration files — configure via API: quiesce.arm({ deadline: 30000 })
  • Startup lifecycle — quiesce only handles shutdown
import { quiesce } from "quiesce";

app.get("/health", (req, res) => {
  if (quiesce.isDraining) return res.status(503).json({ status: "shutting-down" });
  res.json({ status: "healthy" });
});

quiesce.add("http-server", () => server.close());
quiesce.arm();

Related Packages

Caching & Concurrency:

Text Processing:

  • @azghr/shorn — Truncate strings by byte budget without breaking graphemes
  • seriatim — Sequential processing utilities

HTTP & Network:

  • forbear — Read server rate-limit instructions from HTTP responses
  • forestall — Delay execution until a condition is met
  • obviate — Render operations unnecessary through caching

System & Process:

  • sortition — Deterministic percentage rollouts and A/B bucketing
  • stanch — Stop flows or operations based on conditions

Utilities:

  • expunge — Remove or exclude items from collections
  • occlude — Hide or mask data and functionality
  • placemark — Geographic location and mapping utilities
  • specie — Currency and financial calculations

License

MIT