recipes / graceful-shutdown / hono
Graceful shutdown with Hono
Hono is runtime-agnostic. Close the server the adapter gave you, on Node or on Bun.
Hono only routes requests. Listening and shutting down belong to the runtime adapter, so the shutdown code depends on where you run it.
Node.js
serve() from @hono/node-server returns a Node.js http.Server.
import { serve } from "@hono/node-server";
import { Hono } from "hono";
const app = new Hono();
let ready = false;
app.get("/healthz", (c) => c.text("ok"));
app.get("/readyz", (c) => c.text(ready ? "ready" : "not ready", ready ? 200 : 503));
app.get("/", (c) => c.json({ message: "hello" }));
const server = serve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000), hostname: "0.0.0.0" }, () => {
ready = true;
});
function shutdown() {
ready = false;
server.close((err) => process.exit(err ? 1 : 0));
setTimeout(() => process.exit(1), 10_000).unref();
}
process.on("SIGTERM", shutdown);
process.on("SIGINT", shutdown);
Bun
Bun.serve() returns a server whose stop() waits for in-flight requests by default.
const server = Bun.serve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) });
async function shutdown() {
ready = false;
setTimeout(() => process.exit(1), 10_000).unref();
await server.stop();
process.exit(0);
}
Notes
- On Node.js 18, add
server.closeIdleConnections()afterserver.close(). Node.js 19 and newer do it for you. server.stop(true)on Bun kills in-flight requests. Leave the argument out.- Deno: pass an
AbortSignaltoDeno.serve()and abort it in the handler.
See it applied
- examples/frameworks/hono in the repository
- examples/full - every recipe applied to one app
Updated 2026-09-10 · tags: hono, signals, shutdown, bun · edit on GitHub