← experimental
Contents
  1. Definition
  2. Structural (Static) Coupling
  3. Operational (Runtime) Coupling
  4. Contract Coupling
  5. Coupling at the Integration Style Level
  6. Coupling and Architecture Quanta
  7. Managing Coupling
  8. Coupling Signals in Practice (Nygard)
  9. How Different Sources Treat It
  10. Related Concepts

Definition

Coupling is the degree to which one component depends on another — such that a change to one requires a corresponding change in the other, or that the failure or unavailability of one affects the other's ability to function. Reducing coupling is one of the primary levers architects use to enable independent deployability, testability, and evolutionary change.

Coupling is not a single dimension. Different sources isolate structural coupling, runtime coupling, deployment coupling, domain coupling, and contract coupling — each requiring different techniques to manage and each visible at different stages of the software lifecycle.

Structural (Static) Coupling

Structural coupling is measurable at compile time from the dependency graph.

Afferent coupling (Ca): number of external components that depend on a given component (fan-in). High Ca → widely used; changes are risky and must preserve backward compatibility.

Efferent coupling (Ce): number of external components a given component depends on (fan-out). High Ce → fragile; changes elsewhere propagate in.

Robert Martin's derived metrics (package-level):

  • Abstractness (A): ratio of abstract types to total types. A = 0 → concrete; A = 1 → fully abstract.
  • Instability (I): Ce / (Ca + Ce). I = 0 → stable (hard to change); I = 1 → unstable (easy to change).
  • Distance from Main Sequence (D): |A + I − 1|. Components with high D fall into the Zone of Pain (concrete + stable = can't be changed) or Zone of Uselessness (abstract + unstable = nothing depends on it).

Connascence generalises structural coupling: two components are connascent if a change to one requires a change to the other to maintain correctness. Static connascence forms (Name, Type, Meaning, Position, Algorithm) are compile-time and preferred; dynamic connascence forms (Execution, Timing, Values, Identity) are runtime and stronger. The strength of connascence — combined with the distance between the coupled elements — determines the architectural cost of the coupling. See Modularity for the full taxonomy and Page-Jones' and Weirich's rules.

Operational (Runtime) Coupling

Runtime coupling describes dependencies that only become visible when the system is running.

Newman's four coupling types (→ Monolith To Microservices ch. 1), grounded in Parnas' 1971 information hiding principle:

Type Description Severity
Implementation Service A depends on B's internal structure (e.g., calls B's database directly) Most dangerous — violates information hiding entirely
Temporal A can only function when B is available simultaneously (synchronous calls) Reduces robustness; eliminated by async messaging
Deployment A and B must be deployed together Negates independent deployability
Domain A needs data from B's domain to function Unavoidable but should be minimised

A service pair can have low structural coupling but high temporal coupling if they make synchronous calls — structural analysis tools cannot detect runtime coupling.

Dynamic coupling dimensions (→ Software Architecture The Hard Parts ch. 2): across distributed service boundaries, coupling has three interlocking runtime dimensions:

  • Communication: synchronous vs asynchronous — synchronous creates temporal coupling
  • Consistency: atomic vs eventual — distributed atomic transactions merge quanta
  • Coordination: orchestrated vs choreographed — orchestration centralises control coupling

These three binary dimensions produce 2³ = 8 distinct distributed workflow patterns. See Saga for the full taxonomy.

Contract Coupling

Contract coupling is the degree to which a component is constrained by the specification of the interface it consumes or produces (→ Software Architecture The Hard Parts ch. 13).

Strict vs loose contracts: strict contracts require exact adherence to names, types, and ordering (gRPC/Protobuf). They give build-time verification but cascade breaking changes to all consumers. Loose contracts (plain JSON, REST additive fields) enable independent evolution at the cost of schema governance discipline.

Stamp coupling (over-specification): passing a large data structure where the consumer only needs a small part ties the consumer to the producer's full schema. Every change to unused fields becomes a potential breaking change. The rule: keep contracts at a "need-to-know" level. Stamp coupling can be used deliberately to carry workflow state in choreographed sagas — a legitimate trade-off.

See Contracts for consumer-driven contracts as a mechanism to get loose coupling with contract fidelity guaranteed by tests.

Coupling at the Integration Style Level

At the integration level, the choice of integration style sets the baseline coupling between applications (→ Enterprise Integration Patterns ch. 2):

Style Coupling characteristics
File Transfer Loosest — applications share only a file format; maximal temporal decoupling
Shared Database Schema coupling across all participants; any schema change affects every consumer
Remote Procedure Invocation Interface coupling + synchronous temporal coupling; callers must know callee's address
Messaging Channel coupling only; temporal decoupling via async delivery

See Integration Styles for decision criteria between styles.

Coupling and Architecture Quanta

Static coupling (shared databases, frameworks, messaging infrastructure) determines architecture quantum boundaries. Any shared coupling point collapses all services that depend on it into a single quantum — a shared database makes all its consumers one quantum even if they have separate codebases.

Dynamic coupling (runtime communication patterns) determines how independently quanta can operate. Synchronous calls merge operational characteristics; async messaging allows separate quanta to evolve and scale independently.

2PC across quantum boundaries effectively merges them: both services share fate at the transaction boundary. This is why microservices require saga/eventual consistency patterns — preserving quantum independence requires abandoning distributed ACID.

See Architecture Quantum for the full quantum model.

Managing Coupling

Information hiding (Parnas, 1972): stable module interfaces should hide volatile internals so that internal changes do not propagate to consumers. Applied to classes: no caller should depend on implementation choices inside a class (→ A Philosophy Of Software Design ch. 5). Applied to services: no service should depend on another's internal implementation — only its public API (→ Monolith To Microservices). The principle is scale-invariant.

Temporal decomposition (Ousterhout, → A Philosophy Of Software Design ch. 5): a module design anti-pattern where structure mirrors execution order rather than knowledge ownership. When the same knowledge is needed at multiple execution points, temporal decomposition forces it into multiple modules, creating backdoor information leakage. Fix: structure modules around what knowledge they own, not when they execute.

Connascence rules (→ Modularity):

  • Minimise overall connascence by breaking the system into encapsulated elements
  • Minimise connascence that crosses encapsulation boundaries
  • Convert strong connascence forms to weaker ones (Rule of Degree)
  • As distance between elements increases, use weaker connascence (Rule of Locality)

For integration coupling:

  • Prefer loose contracts + consumer-driven contract tests over strict contracts for independently-evolving services
  • Prefer async messaging over synchronous RPI to eliminate temporal coupling
  • Prefer per-service databases over shared databases to eliminate schema coupling
  • Limit stamp coupling to deliberate workflow-state passing in choreography

Orthogonal coupling: operational concerns (observability, security, rate limiting) are orthogonal to the business domain — not part of any bounded context, but needed by every service. Implementing them as sidecars rather than shared libraries keeps them out of the structural dependency graph (→ Reuse Patterns).

Fowler's First Law of Distributed Object Design: don't distribute your objects. In-process calls are orders of magnitude faster than remote calls. A local interface should be fine-grained (many small methods); a remote interface must be coarse-grained (few, chunky calls). You cannot have both for the same object. The solution is to cluster (run multiple copies of a single process) rather than split objects across processes. When a process boundary is unavoidable, isolate it with a Remote Facade (coarse-grained wrapper around fine-grained internal objects) and use a Data Transfer Object to bundle data for the crossing. Never expose fine-grained objects directly over a network (→ Patterns Of Enterprise Application Architecture ch. 7).

Coupling Signals in Practice (Nygard)

Nygard (→ Release It ch. 16) identifies two practical signals that indicate unaddressed coupling:

Coordinated deployments: if provider and consumer must be updated at the same time, the interface is not backward-compatible — a coupling contract failure. Resolution: rework the interface to be backward-compatible (see Api Design) or treat the new interface as a new route and leave the old one in place during consumer migration.

Concept leakage: when an upstream system's internal data-model concept is exported into downstream systems that have no need for it. Example: a "price point" concept (an internal mechanism for bulk repricing) propagated into every downstream feed, requiring every system to model a concept it needed only because the upstream data was incomplete. Resolution: flatten when publishing — downstream consumers should receive resolved values, not the upstream's internal model. Concept leakage creates semantic and operational coupling that resists future change far more than structural coupling does.

How Different Sources Treat It

Source Perspective
Fundamentals Of Software Architecture Structural treatment: Ca/Ce metrics, Martin's A/I/D metrics, connascence taxonomy (static vs dynamic forms, strength spectrum)
Software Architecture The Hard Parts Applies structural metrics to decomposition feasibility; static/dynamic coupling distinction for quanta; 3D dynamic coupling space (communication × consistency × coordination)
Monolith To Microservices Operational taxonomy: implementation, temporal, deployment, domain coupling types; grounded in Parnas' information hiding
Building Evolutionary Architectures Quantum as coupling unit; synchronous connascence as quantum boundary; 2PC as the "strong nuclear force" that merges quanta
Enterprise Integration Patterns Integration-style coupling spectrum (File Transfer → Messaging); strict/loose contract spectrum; stamp coupling as anti-pattern and legitimate workflow mechanism
Patterns Of Enterprise Application Architecture First Law of Distributed Object Design; fine-grained (local) vs coarse-grained (remote) interface distinction; Remote Facade + DTO as the canonical distribution boundary pattern; clustering as the alternative to object distribution (ch. 7)
Release It Coordinated deployments as coupling signal; concept leakage (upstream internal data-model concepts exported to downstream systems); flatten-when-publishing as the mitigation
A Philosophy Of Software Design Information hiding (ch. 5): design decisions embedded in implementation, invisible through interface; temporal decomposition as the primary cause of information leakage at the class level; private fields ≠ hidden information
  • Modularity — connascence taxonomy; Ca/Ce/A/I/D metrics; Newman's operational coupling types in full detail
  • Architecture Quantum — static and dynamic coupling as quantum boundary determinants
  • Contracts — strict/loose contract spectrum; stamp coupling; consumer-driven contracts as coupling governance
  • Integration Styles — integration style choice as the baseline coupling decision
  • Saga — semantic vs implementation coupling; 8-type dynamic coupling taxonomy
  • Reuse Patterns — orthogonal coupling; shared library vs sidecar coupling trade-offs
  • Distributed Transactions — 2PC as a coupling mechanism that merges quanta
  • Sync Vs Async Communication — decision guide for when temporal coupling is acceptable vs when to break it with async messaging