The restart you keep postponing
Reboot debt · July 11, 2026 · 6 min read
Ask a patch management console what proportion of the fleet is patched and it will give you a confident number. The number describes what is on disk. It does not describe what is executing, and on a fleet that has not been restarted in a while those two quantities can differ by a great deal.
The mechanism is unremarkable once stated. A running process maps its code and its libraries at start-up and keeps them. Replacing a shared library on disk does not reach into a process that already has the old copy open; the old file may continue to exist, unlinked from the directory tree, held alive by the file handle. The new code takes effect for the next process that starts. Until then the vulnerable path is still the one executing, in a process the inventory now considers fixed.
Services are the mid-range case: a service restart is enough, and cheap enough that tooling often does it automatically. The kernel is the extreme case, where nothing short of a reboot changes what runs. In between sit the awkward ones — the long-lived daemon nobody wants to touch, the application server holding sessions, the database whose restart needs a coordinated failover and a change ticket.
Deferral is rational, and it accumulates
Each individual deferral makes sense. A restart is a small outage. It is scheduled work, it requires a window, it carries a non-zero chance that the host does not come back cleanly. Weighed against a single patch whose exposure looks modest, waiting is usually the defensible call. So the restart is postponed to the next maintenance window, and then to the one after.
What accumulates is not one pending restart. It is a bundle: every change that has been laid down since the machine last booted, none of which has ever been exercised through a start-up. That bundle has two distinct costs, and they are usually conflated.
The first is residual exposure. The fix is not in effect. Everything the patch was supposed to close is still open, and the reporting says otherwise, which is worse than knowing it is open.
The second is restart risk that grows with the deferral. The chance that a host fails to come back is roughly a function of how much has changed since it last proved that it could. Boot-time configuration, driver versions, filesystem mount logic, service dependency order, licence checks, self-tests — all of these are only tested at boot, and none of them has been tested since the last one. A host with three months of accumulated changes has a start-up path that nobody has run in three months.
Put those together and you get the loop that makes reboot debt so persistent: the longer a host goes without restarting, the more dangerous restarting it becomes, which is an excellent reason to postpone the restart, which increases the danger. It is not a discipline problem. It is a feedback loop, and it will run on its own until something breaks it.
Uptime is not a virtue
The loop is fed by a cultural artefact: treating uptime as a measure of reliability. In a world where a service is provided by one machine, uptime and availability are close to the same thing, and long uptime is genuinely an achievement.
In a world where a service is provided by a pool, they come apart completely. Long uptime on an individual host means only that the host has not been restarted. It is equally consistent with excellent engineering and with a machine so fragile that nobody dares touch it — and the second is more common, because fragility is what causes the deferral in the first place. A host with a year of uptime is more accurately described as a host carrying a year of untested start-up path.
The useful version of the metric is inverted. Track the age of the running state relative to the installed state: how long ago did this process, this kernel, this appliance last start, and how many applied changes are waiting on that restart? That number is derivable from data most estates already collect, and it is almost never derived.
Live patching buys time; it does not clear the debt
Kernel live patching is real and useful. It lets certain fixes take effect on a running kernel without a reboot, which is precisely the intervention the loop above needs.
Its limits matter as much as its capability. It handles changes that can be expressed as a redirect of a function — replace this code path with that one. Changes that alter the layout or meaning of data structures held by a running kernel are not amenable to that treatment, because the existing structures in memory are already the wrong shape. Which fixes fall on which side is not something an operator can determine by reading the advisory; it is a property of the fix, declared by whoever produced the live patch.
So a live-patched host is in a genuinely useful state and a genuinely partial one. Some fixes are in effect, some still wait on the restart, and the pending restart keeps accumulating. Live patching converts an urgent restart into a non-urgent one, which is a substantial win. It does not convert it into no restart, and estates that treat it as though it did end up with enormous uptime and a long queue of deferred structural changes — the worst version of the debt, with the alarm silenced.
Restart often, so that restarting is boring
The way out of a reinforcing loop is to break the reinforcement. If the danger of a restart grows with the time since the last one, then restarting frequently keeps every individual restart small and well-tested. This is the same logic that makes small deployments safer than large ones, applied to the start-up path.
Concretely: coalesce restarts onto a routine schedule and take them whether or not there is a pending change, so that the start-up path is exercised continuously rather than only when something is at stake. A fleet that reboots in rotation on a known cadence discovers its boot-time breakage a few hosts at a time, in a controlled setting, rather than all at once during an emergency rollout when everything is already going badly.
The objection is that each restart costs a small outage, and it does. But the comparison is not against zero. It is against the outage you get when an emergency patch finally forces the issue and a meaningful share of the fleet fails to return.
Count the restart as part of the batch
The practical consequence for a rollout plan is small and important. The restart is not a follow-up task to be tracked separately; it is part of the work of the batch, and it belongs inside the batch’s time estimate and inside its window. A plan whose per-batch duration covers installation but not the restart is understating the work, will not fit the window it was built for, and — worse — will report the batch as complete while the change is not yet in effect.
The definition of done for a batch is not “applied”. It is “applied, restarted, and observed running the new version”.