Lifecycle and graceful shutdown

serve() returns a Server with three members:

MemberDescription
addrPromise<{ hostname, port }> — resolves once the server is listening
stop()Stop accepting new connections and shut down
finishedPromise<void> — resolves when the accept loop has ended

Call await server.stop() for graceful shutdown. In-flight requests are allowed to finish; no new connections are accepted after stop() resolves.

JavaScript
import { serve } from "runtime:http";

const server = serve({ port: 8080 }, (req) => new Response("ok"));
const { port } = await server.addr;

// … run until a signal or condition …

await server.stop();
await server.finished;
console.log("server stopped");

Shutdown on ^C / SIGTERM

esrun handles this for you: it stops accepting, lets in-flight requests answer, and exits 130 / 143.

SituationWhat happens
A server is runningDrain in flight, then exit 128 + signal
No server is runningExit immediately
You installed a handleresrun stays out of the way
Second ^C while drainingExit immediately
Drain outlasts --shutdown-graceExit anyway (default 10000ms)

For your own cleanup, take it over with onSignal:

JavaScript
import { onSignal, offSignal } from "runtime:process";

const shutdown = async (signal) => {
  offSignal(signal, shutdown);
  await server.stop();
  await pool.close();
};
onSignal("SIGINT", shutdown);
onSignal("SIGTERM", shutdown);
Last updated on
Edit this page