Don't Rewrite That 500-Line Daemon: In Defense of the Crusty Old Code That Keeps the Lights On
Photo: NASA Earth RIght Now, Public domain, via Wikimedia Commons
Every shop has one. A daemon nobody wants to claim, written by someone who retired during the Obama administration, sitting in /usr/local/bin like a hermit crab in a shell made of 2009-era Perl. It has no tests. It has no repository history — the original author committed it straight to production from a laptop that is now a landfillsomewhere in Nevada. It has 500 lines of code and fifteen years of uninterrupted uptime.
And every year, someone proposes rewriting it. Every year, I fight that person. Here's why.
The Case for the Crust
Modern engineering culture has a bias we don't like to admit: we equate newness with quality. If a daemon predates containers, it must be technical debt. If it doesn't have a CI pipeline, it must be a liability. If it was written by a guy named Dave who configured it via a series of increasingly urgent Post-it notes, it must be destroyed.
But run the numbers. That daemon has survived three data center migrations, a company acquisition, the great DNS outage of 2016, and every junior admin who poked it with a stick. It has processed billions of events without a memory leak worth paging anyone over. In reliability terms, it is the most battle-tested software you own. You cannot say that about the shiny Rust rewrite that's been in beta for eight months.
Simplicity Is a Feature, Not a Regression
Here's the thing about a 500-line daemon: you can actually read it. All of it. In one sitting. With a coffee. I once audited ours during a compliance review, printed it out, and annotated the whole thing on a flight from Denver to Atlanta. Try doing that with a modern event-driven microservice mesh that spreads its "simple job" across six repos and a Kubernetes operator.
Old homegrown daemons tend to follow a beautiful pattern: read input, do the thing, write output, sleep, repeat. No dependencies beyond libc. No config language that's secretly a programming language. When it breaks — and it rarely does — the failure mode is legible. You can strace it, read the log lines it's been writing since the second Bush era, and know exactly what it's thinking.
The Rewrite Is the Risk
The industry framing is that keeping old code is the risky choice and rewriting is the responsible one. I'd argue the opposite more often than anyone wants to hear. A rewrite means:
- Re-deriving fifteen years of accumulated bug fixes and edge cases that were never documented because Dave fixed them at 3 a.m. and went back to bed
- A migration window where you run both systems, doubling your failure surface
- New dependencies, new CVEs, new memory footprints, new on-call mysteries
- And after all that, roughly the same behavior, but now with a YAML config layer nobody fully trusts
I've watched two rewrite projects die at my current job alone. Both replacement daemons eventually did less than the original, slower, with better dashboards. The old daemon is still running. The new ones are running, too, technically, in the sense that their processes exist. Whether they're doing anything is a question for the interns.
When You Actually Should Retire It
Look, I'm not a luddite. There are legitimate reasons to put an old daemon down: it depends on a library with no security patches since the netbook era, it runs as root because running as root was a lifestyle in 2007, or the one person who understands its failure modes is two weeks from retiring and taking the knowledge to a lake house in Michigan.
But notice those are all specific, articulable risks. "It's old" is not a risk. "It's not written in a language we like" is not a risk. Risk is a story about failure modes, and this daemon's failure modes are known, documented in an email thread from 2013, and mostly involve it doing nothing, loudly.
Raise a Glass to the Crusty Ones
So the next time you're tempted to open a ticket titled "Modernize legacy processing daemon," pour one out instead. That ugly little program has been keeping the lights on since before your container orchestration layer had a name. It asks for nothing — no updates, no telemetry, no Slack channel — and it delivers, every single day, without a single standup meeting.
That's not technical debt. That's a veteran. Buy it a drink. Or at least, leave it alone.