Beer & Servers Don't Mix

The Tragedy of Shared Code: Why Your Most Critical Infrastructure Is Already Dying

Or: Nobody Owns the Basement, and Now the Whole Building Is Sinking

There’s a phenomenon in urban planning called “the tragedy of the commons.” It describes what happens when everyone has access to a shared resource but nobody has responsibility for maintaining it. The pasture gets overgrazed. The fishing grounds get depleted. The village well becomes polluted.

Your shared codebase is that village well.

As Garrett Hardin observed in his seminal 1968 paper, “Freedom in a commons brings ruin to all.” He was writing about population dynamics and grazing rights, but he could have been describing your core authentication service — the one that seven teams depend on and nobody wants to touch.

I’ve been thinking about this a lot lately, watching teams at Agoda navigate the gravitational pull toward entropy that affects every piece of shared infrastructure. The pattern is devastatingly consistent: the more critical the code, the less anyone wants to own it. And the less anyone owns it, the faster it rots.

The Bystander Effect in Your Repository

You’ve seen this play out. There’s that one service — maybe it’s your payment processing layer, maybe it’s your API gateway — that everyone depends on and nobody maintains. Not because people are lazy or incompetent, but because of a psychological phenomenon that social scientists have documented extensively: the bystander effect.

When there are many potential helpers, the sense of personal responsibility diffuses. “Someone else will handle it.” “The platform team probably owns that.” “I think Somchai’s Team touched it last quarter.”

Meanwhile, the code accumulates workarounds like sediment. Each team that needs a change takes the path of least resistance: shoehorning in their feature while changing as little as possible, because nobody fully understands why everything is there. The original architecture becomes buried under layers of compromise.

The basketball coach Phil Jackson had a saying about team dynamics: “The strength of the team is each individual member. The strength of each member is the team.” But what happens when nobody feels like a member of the team responsible for the foundation? The foundation crumbles while everyone watches, each assuming someone else is monitoring the cracks.

The Trolley Problem of Refactoring

Here’s where it gets philosophically uncomfortable.

Imagine you’re a developer who sees clearly that a critical shared service needs refactoring. The code is convoluted, inconsistent, fragile. You could spend a sprint cleaning it up, making it comprehensible, reducing the surface area for bugs.

But the moment you touch it, you own the consequences. If your refactoring introduces a regression — even a minor one — you’re the person who broke production. You actively caused harm. If you do nothing, and bugs continue to emerge from the existing mess, that’s just… the mess. Passive decay that nobody can trace to a decision.

This is the trolley problem of software engineering. People would rather passively let multiple bugs exist than be actively responsible for introducing one. The rational individual choice is inaction. The collective outcome is decay.

And management often reinforces this dynamic. When someone refactors shared code and it causes an incident, there’s a post-mortem. When that same code causes incidents because nobody refactored it, well, that’s just technical debt — unfortunate but not attributable.

Features Over Maintenance Is Locally Rational

Every individual contributor faces incentives that favor new features over maintenance. New features are visible, demonstrable, career-advancing. They show up in sprint demos and quarterly reviews. “I shipped the new recommendation engine” is a story. “I made the authentication service 15% more comprehensible” is not.

This isn’t a failure of character. It’s rational behavior under the incentive structures we’ve created. The economist Charles Goodhart put it succinctly: “When a measure becomes a target, it ceases to be a good measure.” We measure feature velocity, so we optimize for feature velocity. Maintenance work becomes overhead at best, invisible at worst.

The result is predictable. Shared infrastructure gets treated like commons land — something to extract value from, not invest in. Each team asks “what’s the minimum I need to change to get my feature working?” rather than “how can I leave this better than I found it?”

And here’s the kicker: critical infrastructure often starts as research code or proof-of-concept implementations that were never intended to bear load. A small prototype becomes a small service becomes the load-bearing column of your entire architecture. By the time anyone realizes how critical it is, the technical debt has compounded beyond any individual team’s capacity to address.

The Vicious Cycle of Fear-Driven Development

Code entropy creates fear. Fear drives conservative behavior. Conservative behavior accelerates entropy.

When engineers are afraid to change code because they don’t understand what might break, they default to the safest possible approach: changing as little as possible, working around problems rather than fixing them. Each workaround adds complexity. Each added complexity increases fear of future changes.

I’ve watched this cycle turn competent engineers into archaeologists. They spend more time excavating context — who wrote this, when, why, what does this comment from 2019 mean — than actually solving problems. Tribal knowledge becomes essential: “Oh, you need to talk to Namfon about that service. She’s the only one who knows why it does that thing on Thursdays.”

Eventually, you reach a tipping point where the cost of change exceeds the value of change. That’s when teams start having conversations about rewrites. Which, as anyone who’s survived one knows, rarely solve the underlying dynamics that caused the decay in the first place. You just reset the clock while preserving the organizational patterns that accelerated the rot.

What Actually Works (When It Works)

Let me be honest: there’s no silver bullet here. These are systemic problems, and systemic problems require systemic solutions. But I’ve seen some approaches slow the decay meaningfully.

Make shared code ownership explicit and resourced. Not in the “this is everyone’s responsibility” sense, which means it’s nobody’s responsibility. Assign teams or individuals with dedicated time — not 10% time that always gets consumed by feature work, but real, protected capacity. At Agoda, we recommend team spend 30% tech time precisely because we learned that discretionary maintenance never survives contact with product deadlines.

Make the cost of decay visible. If your shared services are degrading, that shows up somewhere — in deployment frequency, in incident rates, in how long simple changes take. Measure these things. Make them part of the conversation when leadership asks why velocity is declining. Technical debt is invisible until you make it visible, and what gets measured gets managed.

Reward maintenance work. This requires cultural change, which is the hardest kind of change. But engineers will respond to incentives. If cleaning up shared infrastructure is recognized, celebrated, and reflected in career progression, people will do it. If it’s invisible, they won’t. I give out Custom Tshirt and post in large public slack channels, the slack post give it meaning, and the Tshirt when its warn around the office provides a reminder.

Shorten feedback loops. Fear decreases when the cost of mistakes decreases. If you can deploy confidently, knowing that problems will be caught quickly and reverted easily, you’re free to make changes that actually improve the system. Feature flags, canary deployments, comprehensive observability — these aren’t just operational nice-to-haves. They’re courage-enabling infrastructure.

Develop shared taste. This might be the most underrated factor. When teams genuinely agree on what “good” looks like, maintenance happens naturally because people feel the friction of decay. When there’s no shared aesthetic sense, every decision becomes a negotiation, and the path of least resistance is always to just ship what works.

The Uncomfortable Truth

As the historian Will Durant observed, “A great civilization is not conquered from without until it has destroyed itself from within.” He was talking about the fall of Rome, but the pattern applies to codebases too. The external threats — changing requirements, new competitors, market pressures — don’t kill shared infrastructure. What kills it is the internal erosion of ownership, the gradual accumulation of compromise, the slow drift from “we should fix that” to “don’t touch that, nobody knows how it works.”

Your most critical code is rotting right now. Not because anyone wants it to, but because the default state of shared resources is decay. The only question is whether you’re going to manage that decay thoughtfully or wake up one day wondering why everything takes longer than it used to.

The next time someone asks why you can’t just ship faster, remind them that speed without maintenance is just borrowing velocity from your future self. And compound interest is a harsh creditor.

Now, if you’ll excuse me, I need to go check on that service we’ve been meaning to refactor for the past eighteen months. Someone needs to be the one who actually touches it, and apparently today that someone is me. Wish me luck — I’ll be the one holding the on-call phone tonight.