
The first time I touched government code, it was a Perl script from 2016 that printed checks for a state benefits program. It had a 47-line subroutine called do_thing() whose last working maintainer had retired in 2009. The comments were in three languages, none of them complete. It paid $400 million a year correctly. I have spent years modernizing systems like that one. Federal, state, county. Tax systems, eligibility engines, benefits portals, court records, risk engines. The work changed how I think about technical debt — not because I learned new techniques, but because the public sector forces you to stop confusing debt with bad code. Most Debt is not bad code In commercial software, "technical debt" usually means: someone shipped something messy under deadline pressure and now we're paying interest. In government, that is sometimes true, but it's rarely the dominant story. The dominant story is that the code was correct for the policy in 1997 and the policy has been amended 41 times since. The Perl script that printed checks was not bad code. It was a record of two decades of legislative change layered on top of an original design. Every nested if was a 2007 amendment. Every special-case constant was a 2012 court ruling. The "debt" was not engineering laziness; it was policy archaeology in source form. You cannot refactor that away without first understanding what each branch represents. The First Thing I Stopped Saying I stopped saying "let's just rewrite it." Every time I have done that in the public sector, I have regretted it within six months. The rewrite always finds out, late, that some quiet line in the legacy code handled the one edge case nobody documented — the case where a beneficiary moves states mid-month and gets a partial payment computed against a holiday calendar from 1984. The replacement I made for "rewrite it": strangle it. Stand a façade in front of the legacy, route one capability at a time to a new service, and never replace anything until you have a contract test that proves the new service matches the legacy bit for bit. It is slow. It is also the only thing that works. Debt you can see vs Debt you cannot After a decade, I have come to divide technical debt into two buckets. The first is the visible kind: deprecated frameworks, missing tests, and copy-pasted code. Engineers see this and want to fix it. The second is invisible: undocumented policy assumptions, oral history of which production levers are safe to pull, and the lone DBA who remembers why a particular index exists. This second kind is the more expensive one and the harder one to repay. Commercial teams underweight invisible debt because their staff turnover is high and their oral history dies young. Government teams overweight it, because the same people work the same systems for 30 years, and an enormous amount of knowledge lives in their heads. When they retire, the system gets unstable in ways that have nothing to do with the code. What stuck with me: a modernization project that does not capture and codify the institutional knowledge is just code rewriting. The capture is the hard part, and it's mostly interviews, diagram-drawing, and writing down the things everyone "just knows". Interest is not always bad The classic framing is that technical debt accrues interest and eventually crushes you. In government, that interest is sometimes the price of stability. A system that processes a million transactions a night with zero downtime over six years is allowed to be ugly. The ugliness is the cost of "not breaking it." Trying to refactor for elegance when the system is running fine is how you cause an outage that makes the local news. The mature move is to ask: is the interest actually hurting us? Sometimes it's, every change takes weeks, deployments are scary, new staff cannot ramp up. That is real interest. Sometimes I would say no — the system works, the team knows it, and the only "debt" is that it offends modern sensibilities. Leave it alone. The Modernization Trap Almost every government modernization I have seen starts with the same slide: a diagram of the legacy on the left and a microservices-on-Kubernetes architecture on the right. The diagram is wrong. Not because microservices are wrong, but because the diagram skips the part where you migrate users, retrain staff, rewrite procedures, integrate with three other agencies' legacy systems, and survive an election cycle without a public failure. The trap is treating modernization as a technology project when it is, at its core, an organizational change project that happens to involve software. The ones that succeed staff a change-management lead with the same authority as the tech lead. The ones that fail proudly declare "we shipped the new platform" while the old platform processes 90% of the actual traffic because nobody trained anyone to use the new one. What I would tell my younger self Three things. First: spend the first month reading the code and talking to the old staff before you propose anything. The system that looks broken from the outside almost always has a reason for everything it does. Second: never break a working integration to fix an aesthetic problem. The integration is somebody's job. Third: write everything down, every assumption, every policy interpretation, every "we do it this way because a long-tenured staffer said so years ago." The document outlives that staffer. The hardest lesson, the one that took me most of the decade to internalize: technical debt in the public sector isn't really technical. It is policy debt, organizational debt, knowledge debt, and trust debt — and only a small slice is actually about the code. The teams that get this build modernizations that hold up. The teams that don't ship beautiful platforms that nobody uses. Why I keep doing it You don't get paid the most doing government modernization. You do not work on the trendiest stack. The release cycles are longer than your patience. The reward is the day a new portal goes live and a benefits caseworker tells you she can do in four minutes what used to take her an hour. Multiply that by a few hundred caseworkers across a state and you've made something that matters to people who will never know your name. That is the part you do not learn from the code. And it's the part that has changed how I think about technical debt everywhere I work now, public or private. The debt that matters is the one that slows down the humans on the other end of the system. The rest is just aesthetics. \ \
View original source — Hacker Noon ↗
