7 min read

Why Good Teams Still Produce Messy Architecture

Why capable teams still create fragmented systems—and how ownership, incentives, executable standards, and system feedback restore coherence.

Listen to this article

Preparing audio…

Architecture

Good engineers can produce a difficult system without making an obviously bad decision. Each team responds rationally to its own deadline, service boundary, budget, and incident queue. The architecture becomes messy when those local decisions accumulate without a mechanism that protects the end-to-end system.

That is why I do not begin an architecture review by asking, “Who designed this?” I begin with a different question: What environment made this design the easiest reasonable choice?

Five environmental forces that cause good teams to produce messy architecture: local goals, delivery pressure, ownership gaps, unusable standards, and missing system feedback
Figure 35. Messy architecture is rarely one reckless decision. It is the compound result of locally sensible choices made without shared ownership, executable standards, or system-level feedback.

Architecture is shaped by the environment around the team

Melvin Conway’s original paper, “How Do Committees Invent?”, connected a system’s structure to the communication structure of the organization that designed it. The point is deeper than drawing team boxes around services. Communication paths, delegation, incentives, and ownership boundaries constrain which designs are practical.

DORA’s guidance on loosely coupled teams makes the operating consequence explicit: teams perform better when they can make, test, and deploy changes independently. Independence, however, does not mean isolation. A team can deploy independently and still create hidden coupling through shared data, duplicated rules, inconsistent identities, or an undocumented operational dependency.

The distinction I use is:

  • Autonomy means a team can make a bounded decision and carry its consequences.
  • Isolation means a team cannot see, influence, or measure the consequences outside its boundary.

Healthy architecture needs the first and actively prevents the second.

Five forces that turn reasonable decisions into system debt

1. Local optimization rewards the visible target

A team is usually measured on the work it can directly control: roadmap delivery, service availability, sprint commitments, cloud cost, or ticket closure. Those measures are useful, but they are incomplete.

Imagine that an onboarding team is measured on conversion and lead time. Reusing the enterprise customer profile requires coordination with another domain and a migration the roadmap did not fund. The team creates a local profile store. The decision improves the local target and may even be the correct short-term choice. At system level, the organization now has two customer identities, two data-retention paths, and a reconciliation problem.

The architecture followed the scorecard. If leaders measure only local throughput, they should expect local designs.

2. Delivery pressure changes the option set

Deadlines do not merely make teams work faster. They remove options that require discovery, coordination, migration, or platform work.

Under pressure, temporary solutions are attractive:

  • copy a validation rule instead of publishing a reusable contract;
  • query another team’s database instead of waiting for an API;
  • add a second queue because the shared event contract is difficult to change;
  • keep a manual approval because automating the control does not fit the release;
  • bypass a platform capability because onboarding takes longer than the feature.

The danger is not the workaround itself. The danger is a workaround with no owner, expiry condition, observable cost, or funded removal plan. “Temporary” is not a lifecycle state.

3. Unclear ownership hides at the seams

Most organization charts assign applications and teams. They do not always assign the relationship between them.

Who owns the meaning of “customer active” across onboarding, compliance, core banking, cards, and payments? Who owns replay after an event contract changes? Who decides whether a failed downstream posting can move a payment back to processing? Who explains the customer outcome when every individual service met its SLO?

If the answer is “all of us,” the operational answer is often “nobody.” Microsoft’s current cloud governance guidance similarly emphasizes explicit function, authority, scope, and interaction across teams. The useful lesson is not to create another committee. It is to make decision rights and escalation paths executable.

I assign four things at every important boundary:

  1. the owner of the business meaning;
  2. the owner of the technical contract;
  3. the owner of the end-to-end outcome;
  4. the authority that resolves a conflict.

Without those, a dependency can be documented and still remain unowned.

4. Standards fail when the compliant path is harder

An architecture standard can be correct and still be ineffective. If it is abstract, hard to discover, slow to approve, or unsupported in the delivery toolchain, teams will route around it.

“Use event-driven integration” is not an executable standard. A usable standard answers:

  • Which event types and ownership rules apply?
  • How are schema compatibility and sensitive data checked?
  • What are the retry, ordering, and idempotency expectations?
  • Which supported libraries, templates, and observability conventions exist?
  • How does a team request a justified exception?
  • Who upgrades the shared capability?

The strongest standards are delivered as paved roads: templates, APIs, tests, policy feedback, examples, and supported runtime capabilities. The Team Topologies material on organization dynamics frames cognitive load as an important design constraint. A standard that transfers all integration and operational complexity to the consuming team has not reduced system complexity; it has only moved it.

5. Missing system feedback allows drift to look successful

A local release can be green while the system becomes harder to change.

Traditional dashboards show latency, errors, availability, and resource use by service. System-level architecture needs additional signals:

  • duplicated capabilities and business rules;
  • cross-domain data ownership violations;
  • synchronous dependency depth;
  • change lead time across team boundaries;
  • exception age and repeated exception patterns;
  • contract-breaking changes and consumer recovery time;
  • incidents where every component met its SLO but the journey failed;
  • cost of changing one business rule across the estate.

Without these signals, architectural drift remains an opinion. By the time it appears as a major transformation programme, the organization has already paid for it through slower delivery, reconciliation, incidents, and coordination.

A synthetic example: the “simple” eligibility rule

Consider a synthetic eligibility rule used by customer onboarding, payments, lending, and card issuance. The business wants to change one threshold in six weeks.

Each domain originally implemented the rule locally because its first release had a different deadline. Every implementation is tested and owned. None is careless. Over time:

  1. onboarding stores the rule in a workflow engine;
  2. payments copies it into an API validator;
  3. lending enriches it with a risk attribute;
  4. cards evaluates it overnight in a batch;
  5. reporting reconstructs the outcome from downstream data.

Now a single policy change requires five delivery plans, different effective dates, customer-state reconciliation, and a decision about historical treatment. The architecture problem is not duplicated code alone. It is duplicated authority.

I would not immediately replace every implementation with one central service. That can turn local duplication into runtime coupling. I would first establish a canonical policy owner, a versioned decision contract, common evidence, explicit latency and availability needs, and a migration sequence. Some domains may evaluate locally using the same signed policy version; others may call a shared capability. The system design follows the required authority and failure model—not a slogan about reuse.

Diagnose the environment before prescribing a target architecture

Visible symptom Likely environmental cause Evidence to collect
Duplicate services or rules Local roadmaps and no reusable capability owner Change history, funding boundaries, repeated implementation effort
Direct database access Missing or unreliable domain contract API lead time, incident history, data consumers, unsupported queries
Too many synchronous calls Teams optimize their step, not journey resilience Dependency depth, timeout budget, failure propagation, ownership gaps
Standards ignored Compliant route is slower or poorly supported Onboarding time, exception volume, support tickets, failed controls
Architecture review happens late Governance is an approval gate, not delivery feedback Decision timing, rework, waiting time, unresolved ADRs
“Temporary” components remain No expiry, owner, or funded removal condition Age, usage, operating cost, business dependency

This table prevents a common failure: treating a structural problem as a training problem. Training helps when people do not know the practice. It does not repair a scorecard, funding model, or ownership gap that rewards the opposite behaviour.

The operating system I want around good teams

Make ownership end to end

Give stream-aligned teams a bounded domain and a customer or business outcome, not only a set of components. Publish the contracts they own, the decisions they may take independently, and the situations that require cross-domain resolution.

Use a named owner for journeys that cross teams. This role does not implement every component. It owns the coherence of the outcome, evidence, and unresolved trade-offs.

Turn principles into executable fitness functions

“Services must be resilient” is too vague to govern. An architecture fitness function checks a property continuously: dependency policy, schema compatibility, recovery objective, encryption, ownership metadata, deployment independence, or an allowed data flow.

Use automation for rules that can be tested. Keep human review for trade-offs that genuinely require judgement. Martin Fowler’s explanation of architecture decision records reinforces the complementary discipline: record the context, decision, alternatives, and consequences, then supersede the record when evidence changes rather than rewriting history.

Fund the shared work

Cross-team architecture work cannot survive as spare-time goodwill. Platform capabilities, migrations, contract improvements, and removal of high-cost exceptions need explicit capacity and owners.

I use an architecture investment backlog with evidence: recurring incidents, repeated exceptions, duplicated cost, long change paths, or control gaps. The backlog competes on business and operational impact, not architectural elegance.

Govern exceptions as information

An exception should record the unmet need, risk owner, compensating control, support model, expiry, and review trigger. Repeated exceptions are product discovery for the platform or evidence that the standard is wrong.

The goal is not zero exceptions. It is zero invisible exceptions.

Review outcomes, not diagrams

Architecture reviews should ask whether the environment produces the intended properties:

  • Can teams deploy without coordinating routine changes?
  • Can an incident owner explain an end-to-end failure?
  • Can one business rule change without a programme?
  • Can a team adopt the standard path without waiting for a specialist?
  • Are system risks visible before they become transformation projects?
  • Can an accepted exception be found, measured, and retired?

The diagram is a hypothesis. Delivery and runtime evidence decide whether it is true.

A 30-day intervention

I would start with one painful customer or operational journey, not an enterprise reorganization.

Week 1 — Map the evidence. Trace one recent change or incident across teams. Record waiting, decisions, data ownership, workarounds, and unresolved authority.

Week 2 — Name the seams. Assign business meaning, contract ownership, journey ownership, and escalation authority for the two or three boundaries creating most friction.

Week 3 — Make one standard executable. Replace one policy document with a template, automated check, working example, and exception route.

Week 4 — Change one feedback loop. Add a system-level measure—cross-team change lead time, exception age, duplicated rule count, or journey failure—and put one funded improvement on the roadmap.

This will not “fix the architecture” in a month. It will prove whether the organization can change the environment that keeps reproducing the same architecture.

My design rule

Good teams do not need more slogans. They need a technical environment where the locally easy decision and the systemically healthy decision are usually the same decision.

When they are not, the organization must make the trade-off visible: name the owner, preserve the rationale, measure the consequence, fund the repair, and learn from the exception. Architecture becomes coherent when the operating model produces coherence repeatedly—not when one architect draws a cleaner target state.

References

Engineering discussion

What decision would you make?

Add a question, a field note, or a respectful counterpoint. Comments are for signed-in members so the discussion stays useful and professional.