Skip to content

@nwire/endpoint — alone

Graceful shutdown + health probes for any HTTP framework. Express, Fastify, Koa, NestJS, or a Nwire httpInterface()endpoint() accepts them all.

What it does

  • Listens on a TCP port and serves your handler.
  • On SIGTERM:
    1. Flips readiness to 500 so the load balancer drains.
    2. Waits drainDelay ms.
    3. Stops accepting new connections.
    4. Drains in-flight requests, bounded by drainTimeout.
    5. Runs any registered shutdown hooks in reverse order.
    6. process.exit(0) — or SIGKILL if hardTimeout is exceeded.
  • Optionally exposes /live + /ready on a separate port.

Install

bash
pnpm add @nwire/endpoint

With Express

ts
import express from "express"
import { endpoint } from "@nwire/endpoint"

const app = express()
app.get("/hello", (_req, res) => res.json({ ok: true }))

await endpoint("api", { port: 3000 }).serve(app).run()

With Fastify

ts
import Fastify from "fastify"
import { endpoint } from "@nwire/endpoint"

const fastify = Fastify()
fastify.get("/hello", () => ({ ok: true }))

await endpoint("api", { port: 3000 }).serve(fastify).run()

With NestJS

ts
import { NestFactory } from "@nestjs/core"
import { endpoint } from "@nwire/endpoint"
import { AppModule } from "./app.module.js"

const nest = await NestFactory.create(AppModule)
await endpoint("api", { port: 3000 }).serve(nest.getHttpAdapter().getInstance()).run()

Health checks

ts
import { endpoint, defineCheck } from "@nwire/endpoint"

await endpoint("api", { port: 3000 })
  .serve(app)
  .health({
    port: 9400,
    livenessPath:  "/live",
    readinessPath: "/ready",
    checks: [
      defineCheck("db",    () => prisma.$queryRaw`SELECT 1`),
      defineCheck("redis", () => redis.ping()),
    ],
  })
  .run()

Tuning the shutdown sequence

ts
endpoint("api", { port: 3000 })
  .serve(app)
  .shutdown({
    drainDelay:   10_000,   // wait for load balancer
    drainTimeout: 30_000,   // wait for in-flight requests
    hardTimeout:  45_000,   // force exit after this
  })

See the graceful deploy recipe for the matching Kubernetes YAML.

Dependencies

@nwire/endpoint depends on:

  • http-terminator (drain in-flight requests)
  • lightship (health endpoint + signal handling)

That's it. No transitive Nwire dependencies — drop it into any TypeScript or JavaScript app.

MIT licensed.