Skip to content
Ayhan Sipahi Ayhan Sipahi

Who Owns This Code Now: Accountability vs Blame

Stop asking who wrote the legacy code. This post separates responsibility, accountability, and blame, and shows how to make inherited code owned, not orphaned.

“Whoever wrote this was an idiot” is one of the most common sentences in software, and one of the least useful. It feels like analysis; it answers a question that does not matter. The moment you open a file and change one line, you own its behavior in production, no matter who typed the original code. Authorship is history. Ownership is present tense. For most engineering teams, the durable answer is team-level service ownership backed by a machine-readable registry, a CODEOWNERS file plus a service catalog, and a real on-call rotation. What makes it work is three words teams wrongly treat as synonyms: responsibility, accountability, and blame.

This post is for engineers and leads who keep inheriting orphaned legacy code, on-call rotations with no clear owner, and reviews that end in a name instead of a fix. It separates the three words, then shows how healthy teams make inherited code owned: operated, monitored, and fixed, rather than left without an operator. It does not re-cover the incident review itself; the blameless postmortem model is the companion piece for what to do inside the review.

The Three Words Teams Use as Synonyms

Most ownership arguments are really vocabulary arguments. Teams collapse three distinct ideas into one word and then wonder why nobody answers for anything. Keep them apart and most of the confusion goes away.

WordQuestion it answersHow many peopleWhen it applies
ResponsibilityWho does the work and runs the code today?Can be sharedActive during the work
AccountabilityWho answers for the outcome?Exactly oneCrystallizes after results are known
BlameWho is morally at fault?Rarely usefulOnly genuine negligence or malice

The split comes straight from RACI, the responsibility-assignment matrix. Its canonical rule is that a task can have several Responsible people but exactly one Accountable person; responsibility is task-oriented and shareable, accountability is outcome-oriented and singular. Blame is a third thing entirely. It is moral fault, and it belongs to a category that healthy organizations retire for almost everything except genuine negligence. Confusing accountability with blame is the core error this whole post is trying to undo.

Keep this about code and services, not about decisions. Who is accountable for a decision is a different question, covered in role expectations and team performance. Here the subject is always a running service and who operates it.

Why Blaming the Author Feels Like Rigor

Blaming the previous developer feels rigorous because it produces a clean narrative and a fast close. It is also wrong about how the code got that way, and the wrongness is expensive.

I have caught myself doing this. Opening an unfamiliar module, I muttered that whoever wrote it did not understand the framework. Then I found the commit that explained the constraint I had missed: a vendor API that only accepted requests in that exact shape. The code was not careless. It was a rational response to a situation I could no longer see.

That reflex has a name. The fundamental attribution error, described in Ross’s 1977 work, is our habit of explaining other people’s behavior by their character and our own behavior by our circumstances. Applied to reading code, the previous developer’s “bad” code was usually a sensible answer to a deadline, a data shape, or a tool of the day that you cannot see now. Hindsight makes the bug obvious; it was not obvious under the original constraints.

Chesterton’s Fence is the discipline that stops the reflex. Before you tear down a fence, learn why it was put up. The reformer who sees no use for it should be answered: if you do not see the use, go and find out first, and only then may you remove it. In code, the “fence” is the odd conditional, the retry, the seemingly pointless sleep. Understand the constraint before you delete it.

What makes inheriting and reworking code safe is Weinberg’s idea of egoless programming: we are not our code. Treat the code as an object the team owns, not an extension of the person who wrote it. Once the code is a shared object rather than a personal one, criticizing it and reworking it stops being an attack and starts being maintenance.

Ownership Is Present Tense

Ownership is not a label in a wiki. You own a service when you operate it, monitor it, fix it, and evolve it. Werner Vogels described this operating model in a 2006 interview as “you build it, you run it”: giving developers day-to-day contact with the operation of their software, and with the customer, raised quality because the feedback loop was direct.

When a piece of inherited code fails, three questions run in order. Only the first two have useful answers.

No owner

Owning team found

No

Yes

Inherited or failing code

Who runs it today?

No owner: the real bug is orphaned ownership

Assign an owning team first

Who answers for the outcome?

One accountable team, not the author

Is anyone genuinely at fault?

Almost always no: fix the system, route to a blameless review

Rare: negligence or malice, Just Culture path

Start with who runs it. Find the owning team through CODEOWNERS or the catalog. If there is no owner, the real bug is orphaned ownership; assign an owner before touching the code. Then ask who answers for the outcome: one accountable team, never the original author. Only at the end ask whether anyone is genuinely at fault, and the answer is almost always no. Fault is the rare exception routed to the Just Culture path, not the default. In practice the owner is a first responder, not a defendant.

Making Ownership Machine-Readable

Ownership declared in a wiki evaporates the moment it is tested. Ownership that survives is machine-readable and paged. Two artifacts carry most of the weight.

A CODEOWNERS file maps path patterns to owning teams. When a pull request touches a path, GitHub auto-requests a review from the matching team, and admins can require code-owner approval before merge. The last matching pattern wins, and owners need write access on the repository.

# .github/CODEOWNERS
# Each line maps a path pattern to one or more owning teams.
# The last matching pattern takes precedence.

*                     @acme/platform
/services/billing/    @acme/payments
/services/checkout/   @acme/checkout
/infra/               @acme/platform @acme/sre
*.tf                  @acme/sre

The second artifact is a service catalog. In Backstage, core catalog entities such as Components, APIs, and Systems must declare a spec.owner that resolves to a Group or User, which gives you a single source of truth for who owns each service.

# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: billing-service
  description: Charges and invoices for customer accounts
  annotations:
    github.com/project-slug: acme/billing-service
    pagerduty.com/service-id: PXXXXXX
spec:
  type: service
  lifecycle: production
  owner: team-payments
  system: billing

One caveat matters more than any field. An owner pointing at a defunct team is worse than no owner, because it looks answered while nobody is home. The registry needs a real org-chart source so entries decay loudly, not silently. A useful local signal is the share of services with a named, live owner; track it toward near-total coverage and orphaned services toward zero. Treat it as a homegrown indicator, not a citable benchmark.

There is a real trade-off here. Strict code ownership can create review bottlenecks and “not my code” silos that work against collective code ownership. The fix is to scope ownership to a team, not a person. A named accountable team keeps accountability singular while the code stays collectively editable; team-scoped ownership is not the same as individual gatekeeping.

Ownership Survives Departures, Orphans Do Not

An owning team survives what an owning person cannot: a departure. Individual ownership creates a bus factor of one, and the knowledge leaves with the person. “Software Engineering at Google” names the Genius Myth, ascribing a team’s success to one person, as a trap, and ties durable ownership to a primary and a secondary owner plus documentation. Ownership is a team property; the lone hero is a risk, not an ideal.

Yes

No

Service has an owning team

Owner leaves or team reorgs

Transfer ritual performed?

New owning team: runbook, dashboards, on-call, access, known issues handed over

Orphaned service: no owner, no on-call

Next incident has no first responder

When a person or team leaves, ownership is transferred through a ritual, not silently dropped. The ritual hands over the runbook, the dashboards, access, known issues, and the pager. Skip it, and the service is orphaned: the next incident has no first responder, and the conversation defaults back to “who wrote this?” A high bus factor is what makes the transfer possible in the first place. Fold operational ownership into your Definition of Done, so a feature is not finished until a named team owns running it.

The Question Leaders Ask

The question a leader asks in public teaches the whole team what to do next. “Who broke this?” asked in the open teaches people to hide the next problem, which is the opposite of the accountability the leader wanted. Replace it with a different question: which service, which owner, and what do we change?

A bug surfaces in inherited code

Unhealthy question: who wrote this?

Healthy question: who owns this, what do we change?

Author blamed, no one adopts the code

Code stays orphaned

Bug recurs, still no owner

Owning team responds as first responder

System fix ships

Ownership reinforced, registry stays current

Amy Edmondson’s psychological safety is the precondition for the healthy loop. It is the shared belief that it is safe to speak up with questions, concerns, and mistakes. It is not about being nice; it is candor without fear of punishment. Without it you get hidden problems, not honest ownership. Leaders reinforce it by absorbing blame and distributing credit, which is also the genuinely useful half of Extreme Ownership.

When to Override

Team-level service ownership is the default, but two cases justify a different setup, and one popular framing needs a guardrail.

For small teams or low-criticality code, individual ownership is acceptable. The bus-factor risk is real but tolerable when the code is not on the critical path and the team is small enough that everyone can read it. The version to avoid is informal “ask X on Slack” ownership, because it leaks with every reorg and leaves no artifact behind.

Extreme Ownership, the leadership idea that there are no bad teams, only bad leaders, is useful and dangerous in the same breath. Its strength is that a leader absorbs blame and owns the outcome. Its failure mode is re-privatizing a systemic failure back onto one person, the exact thing blameless culture exists to fix. The synthesis is narrow and important: own fixing the system, not being personally at fault. A leader owns the outcome and the repair; they do not convert a system gap into personal guilt.

“You build it, you run it” raises quality, but full, undifferentiated ownership can become a burnout tax. Critics link the model to on-call load and cognitive-load sprawl when every team runs its own everything. The platform-engineering counter keeps the principle and moves undifferentiated load to a platform team through paved roads, sometimes called golden paths. The caveat is honest: a poorly built platform just relocates the load rather than removing it. “You own it” needs a paved road, or ownership becomes a tax people quietly refuse to pay.

Common Pitfalls

A few failure modes show up repeatedly, each with a concrete fix.

  • Rewriting inherited code before understanding it. Learn why the fence is there before you remove it.
  • Declaring ownership in a wiki with nothing behind it. Ownership must live in CODEOWNERS or the catalog and carry a pager.
  • Five people “accountable” for one outcome. Exactly one accountable team; the rest are responsible.
  • Treating accountability as a synonym for blame. Accountability answers for the outcome and drives the fix; blame assigns moral fault and rarely helps.
  • Letting services go orphaned on departure. Make an ownership-transfer ritual part of offboarding and every reorg.
  • A public “who broke this?” from leaders. Model the healthy question, absorb blame, and distribute credit.

Conclusion

The default holds for almost everything. Scope ownership to a team, make it machine-readable in CODEOWNERS and a service catalog, back it with an on-call rotation, and keep the three words apart. Responsibility is who runs it, accountability is the one team that answers, and blame is the rare exception you route to a Just Culture review. Reach for individual ownership only on small, low-criticality code, and pair “you build it, you run it” with a paved road so ownership does not turn into burnout.

If you do one thing after reading this, open your most-inherited service and check whether it has a named, live owner in a registry. If it does not, that is the real bug, and it is a more useful finding than the name of whoever wrote the code.

References

Related posts