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

@ololoepepe/termination-handler

v0.3.0

Published

Process termination handler

Readme

@ololoepepe/termination-handler

Graceful process termination for Node.js services.

Listens for termination signals (SIGTERM / SIGINT by default), runs the shutdown handlers you registered — in priority order — and then exits. If the handlers take too long, the process is killed anyway, so a stuck connection can never leave a container hanging until the orchestrator SIGKILLs it.

Installation

npm install @ololoepepe/termination-handler

Requires Node.js >= 24. Written in TypeScript — the type declarations ship with the package, so there is no @types/… to install.

To terminate HTTP servers gracefully (draining keep-alive connections) also install the optional peer dependency:

npm install http-terminator

Without it everything else still works — see HTTP servers below.

Usage

import {TerminationHandler} from '@ololoepepe/termination-handler';

const terminationHandler = new TerminationHandler();

terminationHandler.attachHttpServer(server);
terminationHandler.attachKnexInstance(knex);
terminationHandler.attachRedisInstance(redis);

terminationHandler.installHandler(async () => {
  await flushMetrics();
});

That is the whole setup: from this point on, a SIGTERM drains the HTTP server first, then closes the database and Redis connections along with your own handler, then exits with code 0.

How termination works

  1. A termination signal arrives.
  2. A "forced termination" timer starts. If it fires before the handlers are done, the process exits with code 1 — no matter what is still pending.
  3. Handlers run grouped by priority, in ascending order. All handlers within one priority group run concurrently; the next group only starts once the previous one has fully settled.
  4. Once every group has settled, the timer is cleared and the process exits with code 0.

Handler failures are never fatal: every group is awaited with Promise.allSettled, and the built-in attach* helpers swallow errors from the underlying client. A connection that refuses to close cleanly will not prevent the remaining handlers from running.

Priorities exist so that things get shut down in a sensible order. Servers that accept inbound traffic (attachHttpServer, attachWsServer) default to priority 0, so they stop accepting work before the resources they depend on — databases, queues, caches — are torn down at the default priority 1.

API

new TerminationHandler(options?)

| Option | Type | Default | Description | | --- | --- | --- | --- | | forcedTerminationTimeout | number | 14000 | Milliseconds before the process is forcibly exited with code 1. | | gracefulTerminationTimeout | number | 10000 | Milliseconds http-terminator waits for in-flight requests before destroying sockets. | | terminationSignals | NodeJS.Signals[] | ['SIGTERM', 'SIGINT'] | Signals to listen for. |

Keep forcedTerminationTimeout below your orchestrator's grace period (for example Kubernetes' terminationGracePeriodSeconds, 30s by default) so that the process gets to exit on its own terms rather than being SIGKILLed. The default pair leaves a 4s margin between the graceful and the forced timeout.

installHandler(handler, priority = 1)

Registers a shutdown handler. handler is called with no arguments and may return a promise. Lower priority runs earlier.

terminationHandler.installHandler(async () => {
  await consumer.stop();
}, 0);

attach* helpers

Convenience wrappers around installHandler for common clients. Each one is a one-liner around the library's own shutdown method, with errors suppressed.

| Method | Calls | Priority | | --- | --- | --- | | attachHttpServer(server) | http-terminator | 0 | | attachWsServer(server) | server.close() | 0 | | attachAmqpInstance(instance) | instance.close() | 1 | | attachFirebaseAdminAppInstance(instance) | instance.delete() | 1 | | attachFirestoreInstance(instance) | instance.terminate() | 1 | | attachKnexInstance(instance) | instance.destroy() | 1 | | attachRedisInstance(instance) | instance.quit() | 1 |

Apart from attachHttpServer, the helpers are structurally typed — anything exposing the right method works, so they are not tied to one particular client library. attachHttpServer is the exception: it accepts an http.Server, an https.Server or an http2.Http2SecureServer, because that is what http-terminator itself supports.

The shapes are exported as AmqpInstance, FirebaseAdminAppInstance, FirestoreInstance, KnexInstance, RedisInstance and WsServer, alongside TerminationHandlerOptions and TerminationHandlerCallback.

HTTP servers

attachHttpServer uses http-terminator to shut a server down gracefully: it stops accepting new connections, lets in-flight requests finish, and only then destroys the lingering keep-alive sockets. http-terminator is an optional peer dependency, imported lazily inside the handler, so it is only needed if you actually call this method.

If it is not installed, the handler logs a warning and falls back to server.close(). That still stops new connections from being accepted, but it does not drain keep-alive sockets — close() waits for existing connections to end on their own, which for keep-alive clients may not happen before forcedTerminationTimeout kicks in. Install http-terminator if you serve keep-alive traffic.

Development

| Command | What it does | | --- | --- | | npm run lint | ESLint over the whole repository. | | npm run typecheck | tsc over src, test and scripts, no emit. | | npm test | The node:test suite; Node runs the TypeScript sources directly. | | npm run build | Compiles src into dist/node/ — the ESM and .d.ts that get published. |

Internal imports go through the #src/*.ts subpath map rather than relative paths. dist/node/ gets its own package.json remapping #src/*.ts to the compiled files, which is what makes those imports resolve for consumers.

License

UNLICENSED — private package.