mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmWeb Backendupdated 22 Sept 2026

stoppable review

Stoppable 1.1.0 decorates a Node HTTP or HTTPS server with `stop(callback)`. It counts active requests on each socket, ends idle keep-alive sockets when shutdown begins, lets active responses finish, and destroys what remains after an optional grace period. Version 1.1.0 added the callback's `gracefully` boolean and removed extra files from the published tarball. The original keep-alive problem is now smaller: Node's own `server.close()` has reaped idle HTTP connections since Node 19, and Node 18.2 added explicit idle and all-connection methods.

Verdict

Stoppable 1.1.0 installed as one 1 MB package with zero audit findings in our sandbox, but Node 19 already folds its main idle-connection fix into `server.close()`. Retain it for tested old-Node support or its forced-deadline callback; new current-Node services should begin with core shutdown methods and explicit resource cleanup.

We installed it

Lab card: what happened when we installed stoppableScreenshot of stoppable documentation
Install✓ · 0.4s1 package on disk · 1 MB
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does stoppable install cleanly?

Yes. In a fresh container with an empty cache, npm install stoppable finished in 0.4s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

Can stoppable run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does stoppable work with both ESM and CommonJS?

Yes. Both import 'stoppable' and require('stoppable') worked in Node 22 in our run. The package is published as CommonJS.

Does stoppable include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

stoppable or http-terminator: which should you use?

http-terminator: Choose it for a promise-based HTTP termination API with a newer package design. Stoppable 1.1.0 installed as one 1 MB package with zero audit findings in our sandbox, but Node 19 already folds its main idle-connection fix into server.close().

When should you not use stoppable?

The service runs only on Node 19 or newer and merely needs server.close() to reap idle keep-alives. Node core already does that.

API stability4/5The API is one decorator, one constructor-time grace value, and one `stop` callback. Version 1.1.0's only user-facing addition was the `gracefully` callback result, and no release has changed it since November 2018. That small surface is easy to keep compatible. The cost is an untyped mutation of the server instance plus `_pendingSockets` state, with no documented contract for calling `stop` more than once.
Docs3/5The README defines the server argument, grace milliseconds, `Infinity` default, 0 behavior, two callback values, FIN-first socket handling, and the bookkeeping tradeoff. It also includes an old loopback benchmark. The page does not discuss Node 18.2's close methods, Node 19's changed `server.close`, upgraded sockets, HTTP/2, repeated signals, promises, or TypeScript. Its linked motivation accurately describes history but no longer proves a need on current Node.
Maintenance2/5npm published 1.1.0 on November 10, 2018, and GitHub shows the last push on October 31, 2023. The unarchived repository currently combines 28 open issues and pull requests. A 24 KB dependency-free package can keep working without frequent releases, yet Node core changed the exact keep-alive behavior it was built to replace. No new package release explains that platform shift or adds declarations for current projects.
Ecosystem3/5npm counted 5,051,844 downloads in the latest completed week, while GitHub reports 404 stars. It accepts the standard HTTP and HTTPS server objects returned by frameworks such as Express, and its zero-dependency graph limits supply-chain surface. Coverage stops at that server boundary: there are no types, health hooks, WebSocket tracking, HTTP/2 support, signal orchestration, or resource cleanup. Much of its volume can come from older transitive installations.

Use it if

  • A service supports Node older than 19 and needs idle keep-alive sockets closed while active HTTP responses drain.
  • Existing callback-based shutdown code depends on the second `gracefully` result to distinguish a clean drain from a deadline.
  • One HTTP or HTTPS server needs a finite force-close timer, and all other resources already have their own cleanup path.
  • The team can test the decorator's socket bookkeeping against the exact Node version and proxy behavior in production.
Skip it if

Setup reality

We installed stoppable 1.1.0 in 0.4 seconds. The result was one package using 1 MB on disk, with 24 KB unpacked and no direct or peer dependencies. npm audit found zero known vulnerabilities. It is CommonJS without an exports map; require() and ESM import both worked in Node 22. No TypeScript declarations were present. The package declares Node >=4 and npm >=6, while its README calls Node 6 the supported baseline.

Pass an existing http.Server or https.Server plus a grace value in milliseconds. The same instance comes back with stop. A missing grace means Infinity; 0 schedules immediate ending and destruction of tracked sockets. The callback signature is (error, gracefully), with the second value added in 1.1.0. Wrap it yourself if the rest of the shutdown path uses promises. Guard repeated signals because the README does not promise that repeated stop() calls are idempotent.

On shutdown, Stoppable calls server.close(), ends sockets with zero active requests, and waits for response finish before ending busy sockets. When the timer expires it marks the result forced, calls end(), then destroys sockets on the next turn. It watches connection or secureConnection plus HTTP request events. WebSocket upgrades, HTTP/2, raw TCP work, timers, database pools, queue consumers, and child processes remain open unless your signal handler closes them separately.

Our browser bundling attempt failed, which is expected for a Node server decorator. More importantly, modern Node changes the buy decision. Since Node 19, server.close() itself closes idle HTTP connections. Node 18.2 also provides closeIdleConnections() and closeAllConnections(); the latter is forceful and still excludes upgraded protocols. A small local function using those core calls is easier to type on current runtimes. Keep Stoppable where old-Node compatibility or its tested graceful flag still earns the dependency.

Patterns

Add a finite shutdown deadline decorate-server

const http = require('node:http')
const stoppable = require('stoppable')

const server = stoppable(http.createServer(handler), 10_000)
server.listen(3000)

The second argument is milliseconds; omitting it leaves the 1.1.0 default at `Infinity`.

Wrap a server after construction decorate-existing-server

const server = http.createServer(app)
stoppable(server, 15_000)
server.listen(3000)

The decorator mutates and returns the same server by adding `stop` and `_pendingSockets`.

Check whether requests drained observe-stop-result

server.stop((error, gracefully) => {
  if (error) {
    process.exitCode = 1
    console.error(error)
    return
  }
  console.log({ gracefully })
})

Version 1.1.0 added the second boolean; it is false when the grace timer takes the forced path.

Preserve the graceful flag in a promise await-stop

function stopServer(server) {
  return new Promise((resolve, reject) => {
    server.stop((error, gracefully) => {
      if (error) reject(error)
      else resolve({ gracefully })
    })
  })
}

const result = await stopServer(server)

Stoppable 1.1.0 is callback-only, so promise-based lifecycle code needs this local wrapper.

Start shutdown once on SIGTERM handle-sigterm

let closing = false
process.on('SIGTERM', () => {
  if (closing) return
  closing = true
  server.stop((error, gracefully) => {
    if (error || !gracefully) process.exitCode = 1
  })
})

Guard duplicate signals because repeated `stop()` behavior is not documented; close pools and consumers in the same lifecycle separately.

Decorate the server returned by Express stop-express

const express = require('express')
const stoppable = require('stoppable')

const app = express()
app.get('/ready', (_, response) => response.send('ok'))
const server = stoppable(app.listen(3000), 10_000)

Express returns a Node HTTP server, but this wrapper does not change readiness or close application dependencies.

Track an HTTPS server stop-https

const https = require('node:https')
const stoppable = require('stoppable')

const server = stoppable(https.createServer(tlsOptions, app), 10_000)
server.listen(443)

For HTTPS, 1.1.0 tracks `secureConnection`; upgraded WebSocket and HTTP/2 lifecycles remain separate.

Use a zero-millisecond grace force-sockets

const server = stoppable(http.createServer(handler), 0)
server.stop((error, gracefully) => {
  console.log({ error, gracefully })
})

A 0 grace ends and then destroys all tracked sockets without waiting for in-flight HTTP work.

Fail a test when draining times out close-test-server

afterEach(async () => {
  const { gracefully } = await stopServer(server)
  if (!gracefully) throw new Error('server exceeded shutdown deadline')
})

Use a finite grace in tests; the default `Infinity` can leave the test process waiting on one stuck response.

Replace it on current Node use-core-node-shutdown

await new Promise((resolve, reject) => {
  server.close((error) => error ? reject(error) : resolve())
})

// Force only after your deadline:
server.closeAllConnections()

Since Node 19, `server.close()` reaps idle HTTP connections. `closeAllConnections()` is forceful and does not close upgraded protocols.

Alternatives

PackageRegistryPick it when
http-terminatornpmChoose it for a promise-based HTTP termination API with a newer package design.
http-graceful-shutdownnpmChoose it when signal handling and application cleanup callbacks should surround server shutdown.
close-with-gracenpmChoose it to coordinate process signals and cleanup across several resources instead of decorating one server.

More web backend guides

urllib3 · requests · ws · anyio · httpx · undici · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.