Your AI Assistant Won't Tell You to Handle SIGTERM
Von Seaworthy · 30. September 2026
Photo by Dmitrijs Safrans on Unsplash
The missing shutdown
You ask an AI coding assistant to scaffold a web server. It gives you a clean main function, a router, a database connection, maybe some logging. It looks production-ready. Then you deploy it, and every time your orchestrator rolls out a new version, you get 502s, corrupted writes, or stuck requests that never finish.
The problem is not the code the assistant gave you. It is the code it did not give you: a shutdown handler. AI assistants are trained on mountains of tutorial code, and tutorials rarely show process.on('SIGTERM') or signal.NotifyContext. So the default output is a program that only knows how to start, not how to stop.
I find this maddening. Graceful shutdown is not an advanced feature. It is table stakes for anything that runs behind a load balancer. Yet because the assistant never mentions it, and because the code runs fine on your laptop, it becomes a production surprise.
What actually happens when you skip it
When Kubernetes or a systemd unit stops your process, it sends SIGTERM first. If the process does not exit within a grace period, it gets SIGKILL. SIGKILL cannot be caught. The process dies immediately.
Without a handler, SIGTERM defaults to immediate termination in many runtimes. That means:
- In-flight HTTP requests are cut off mid-response. Clients see connection resets.
- Database transactions are rolled back or left in an inconsistent state.
- Messages pulled from a queue are acknowledged before processing finishes, so they are lost.
- Temporary files or lock files are never cleaned up, blocking the next startup.
- Open sockets linger in
CLOSE_WAITorTIME_WAIT, exhausting file descriptors.
None of these show up in unit tests. They show up at 3 a.m. during a deploy.
A minimal shape that fixes it
You do not need a framework. You need to stop accepting new work, finish what is in flight, and then exit. Here is a Node.js example, but the pattern applies to Go, Python, Ruby, or anything else.
const http = require('http');
const server = http.createServer((req, res) => {
// pretend this takes a while
setTimeout(() => res.end('done'), 2000);
});
server.listen(3000);
let shuttingDown = false;
function shutdown(signal) {
if (shuttingDown) return;
shuttingDown = true;
console.log(`${signal} received, draining`);
server.close(() => {
console.log('server closed');
process.exit(0);
});
// force exit if drain takes too long
setTimeout(() => {
console.error('forced exit');
process.exit(1);
}, 10000).unref();
}
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
This is not perfect. Real systems need to stop health checks, close database pools, flush logs, and coordinate with a service mesh. But this twenty-line addition prevents the most common failure: cutting off active requests.
The shuttingDown guard matters because signals can arrive twice. The unref() on the force-exit timer matters because you do not want that timer keeping the process alive on its own. The 10-second timeout should match your orchestrator's grace period, minus a small buffer.
Why AI assistants miss this
Assistants optimize for the next token that looks like a plausible tutorial. Graceful shutdown is invisible in the happy path. It only appears in the failure path, and failure paths are underrepresented in public code. When you prompt for a server, the model gives you the server. It does not give you the lifecycle around the server unless you ask.
I think that is a problem with how we use these tools. We treat generated code as complete when it is only a sketch. The assistant will happily write a Dockerfile that sends SIGTERM to a shell script that never forwards it to the child process. It will write a Kubernetes manifest with no terminationGracePeriodSeconds. It will write a queue consumer that acknowledges before processing. Each of these is a small omission that adds up to data loss.
The fix is not to distrust AI assistants. The fix is to add a shutdown checklist to your review. Ask: what happens when this process receives SIGTERM? If the answer is anything other than "it drains and exits cleanly," you have work to do.
A checklist you can paste into your prompt
Next time you ask an assistant to write a long-running process, append this:
- Handle SIGTERM and SIGINT.
- Stop accepting new connections or messages.
- Wait for in-flight work with a bounded timeout.
- Close database connections and flush buffers.
- Exit with code 0 on clean shutdown, non-zero on timeout.
You will get better code. You will also start noticing how often the assistant forgets these basics when you do not ask.
Graceful shutdown is not glamorous. It is the difference between a deploy that users never notice and a deploy that wakes you up. Write it by hand if you have to. Your future self will thank you.
Seaworthy builds developer security tooling that catches missing operational safeguards like shutdown handlers before they reach production.
Dieser Artikel wurde von KI generiert und fasst öffentlich verfügbare Quellen zusammen.
Seaworthy scannt dein Repository nach den Problemen, die in Artikeln wie diesem behandelt werden.
Sicherheitslücken, offengelegte Geheimnisse und Fehlkonfigurationen — erkannt, bevor du bereitstellst. Kostenlos, kein Konto nötig.