An application of mine died in July. The retirement took a day. The death took ten. The gap between those two numbers is what this is about.

The application had not failed. It was a meal-ideas app, one of the older residents of the fleet, and over time its one genuinely good surface had migrated into the app next door, where it made more sense. What remained was a running service with no reason to run. That turns out to be the hardest kind to kill, because nothing about it looks wrong. It starts cleanly. It answers requests. It backs itself up. Every system it touches reports green.

I did what the manuals say. Stopped the service, disabled it, moved on.

It came back.

Nothing sinister happened. My own recovery system — built to notice a down service and bring it back, because on a fleet this size I cannot be the one noticing — noticed a down service and brought it back. I had told the machine to stop running the thing. I had not told the machine whose whole job is to keep things running. It did its job. For a moment I was genuinely annoyed at a piece of software for working exactly as I had specified, which is a feeling every operator will recognise and no requirements document ever captures.

So the first rule went in the log: a service is not stopped while anything on the box still knows how to start it. Disabled is not dead. The unit files came off the server entirely — not silenced, removed — because the only start command I trust is one that no longer exists.

That prompted the question the rest of the ten days answered: how many places on that server remember an application? I counted six. The unit files. The reverse-proxy route. The TLS certificate. The database. The web root. The monitoring config. Death is all six forgetting, and each forgets differently — the route came out through a pull request, the database was dropped, the directories deleted, the certificate not renewed, the monitor entry removed so the recovery system would stop grieving. Ten days after the retirement, a checklist pass over all six came back empty, and the log got its closing line: teardown verified complete, with a date. Software death is bureaucratic. It should be. The alternative is the kind of death that isn't one.

The code itself is a different matter. Code doesn't die here; it retires in place. There is a directory in the repository called archived/, and the whole application moved into it with its history intact — eighteen directories live there now, fourteen products once you pair the front and back halves. The distinction matters: the repository is where remembering is cheap and useful, and production is where remembering costs money and answers requests. Archive in one, extinction in the other.

I keep a running total of what the fleet holds, and for once the number went down. It is a strange feeling to do weeks of careful work so that there is less of something. Launching is a better story — launching has a screenshot, a first user, a day one. Subtraction has a checklist and a log line. But the fleet is smaller than it was in May, and it is easier to reason about, and every service still running is one I can defend running.

The definition I settled on, for the log and for myself: an application is dead when bringing it back would take a deliberate act. Anything short of that is resting.


This essay first appeared in the Logbook on my personal Substack, where new entries land first.