From e8a32a1a01aa586ed3d38cd0e6ae170ee6acd8f9 Mon Sep 17 00:00:00 2001 From: guitavano Date: Thu, 25 Jun 2026 15:55:22 -0300 Subject: [PATCH] fix(liveness): skip self.close() on SIGTERM outside k8s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deno's HMR and --watch modes use a parent/child process model where the parent sends SIGTERM to signal the child to restart. The liveness middleware's SIGTERM handler was calling self.close(), which kills the process before Deno can complete its restart cycle — causing every dev server to die on the first file change instead of hot-reloading. Only call self.close() in k8s (detected via KUBERNETES_SERVICE_HOST) where SIGTERM means the pod must shut down. Deno runtime flags like --unstable-hmr and --watch are not visible in Deno.args, so detecting dev mode directly is not reliable. Co-Authored-By: Claude Opus 4.6 --- runtime/middlewares/liveness.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/runtime/middlewares/liveness.ts b/runtime/middlewares/liveness.ts index 2cc6418c6..af6c080fa 100644 --- a/runtime/middlewares/liveness.ts +++ b/runtime/middlewares/liveness.ts @@ -65,12 +65,22 @@ const buildHandler = ( } }); }; + // In production (k8s), SIGTERM comes from the kubelet and the process must + // shut down. In local dev, Deno's HMR/watch sends SIGTERM to the child + // process expecting a clean restart cycle — calling self.close() here kills + // the process before HMR can relaunch it, breaking hot-reload entirely. + // Deno runtime flags (--unstable-hmr, --watch) are NOT visible in Deno.args, + // so we detect production by the presence of KUBERNETES_SERVICE_HOST which is + // always injected into k8s pods. + const isK8s = Boolean(Deno.env.get("KUBERNETES_SERVICE_HOST")); try { if (Deno.build.os !== "windows") { Deno.addSignalListener("SIGTERM", () => { const checks = runChecks(); console.log(checks); - self.close(); + if (isK8s) { + self.close(); + } }); } } catch (err) {