@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:- Flips readiness to 500 so the load balancer drains.
- Waits
drainDelayms. - Stops accepting new connections.
- Drains in-flight requests, bounded by
drainTimeout. - Runs any registered
shutdownhooks in reverse order. process.exit(0)— orSIGKILLifhardTimeoutis exceeded.
- Optionally exposes
/live+/readyon a separate port.
Install
bash
pnpm add @nwire/endpointWith 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.