You split the monolith into twelve services. Deployments still require coordinating seven teams. Every release goes out together. Rollbacks cascade across four repositories. You solved the wrong problem.
The problem was never the number of services. The problem was AT8 — Coupling vs Cohesion. Splitting a system does not decouple it. It only moves the coupling from function calls to network calls. The coupling becomes harder to see and harder to fix.
This article names what the tradeoff actually is, why microservices commonly get it wrong, and the signal that tells you your architecture is a distributed monolith wearing a service mesh.
The two poles named precisely
High cohesion means related things live together. A module owns a clear, single responsibility. All logic for that responsibility lives in one place.
Low coupling means components are independent. Changing one does not require changing another. A deployment of one service does not force a deployment of another.
These sound like the same property. They are not. They are two different axes. A system can be high on both, low on both, or high on one and low on the other. AT8 is the tradeoff between them because raising cohesion often raises coupling, and lowering coupling often lowers cohesion.
The tension is precise. High cohesion often requires knowledge of a component's internals. That knowledge creates coupling to those internals. Two modules that must know each other's internals to be cohesive are tightly coupled by that knowledge.
The monolith and the microservice at each extreme
A monolith sits at high cohesion and high coupling. All related code lives in one place — that is the cohesion. Many components depend on many others, share types, share database tables, share transactions — that is the coupling. The monolith is easy to change and hard to change safely. One deployment ships everything.
Microservices sit at low coupling and potentially low cohesion. Each service deploys independently — that is the low coupling, in theory. Business logic for one domain now lives across three services — that is the lost cohesion, in practice. A single business change requires editing three repositories, coordinating three deployments, and hoping the three teams release in the right order.
The distributed monolith is the failure mode. You paid the cost of microservices — network calls, service discovery, distributed tracing, eventual consistency between services — and did not receive the benefit. Deployments still require coordination. A change to one service breaks another. The coupling did not go away. It moved from compile-time to runtime. It became harder to detect and more expensive when it fires.
The correct architecture is not "many services" or "one monolith." The correct architecture is high cohesion within a service and low coupling between services. Neither pole alone is the goal. The pair is the goal.
What sets the dial
The rule is stated by boundary. Within a bounded context, set toward cohesion. Between bounded contexts, set toward low coupling.
Within the payment domain, every rule about how payments work lives in one place. The retry logic, the fraud check integration, the ledger write, the reconciliation job — all of it in the payment service. A payment engineer does not read four repositories to understand a payment. That is cohesion inside the boundary.
The payment service does not know how shipping works. It does not read the shipping database. It does not import shipping types. It knows that a payment succeeded or failed. Shipping listens for the payment event and decides what to do. That is low coupling between the boundaries.
Get the boundary wrong and both properties collapse. If you draw the boundary in the middle of the payment domain — payment authorisation in one service, payment capture in another — you now have low cohesion (payment logic split) and high coupling (they must call each other synchronously for every transaction). Two services, worse than one.
Conway's Law tells you where the coupling will land
Conway's Law (F9 #1) is not an observation about org charts. It is a constraint on architecture. Team structure determines coupling.
Services owned by the same team will be coupled. The team's communication flows through the code because the team talks to itself constantly. Shared types, shared assumptions, shared deployment scripts all appear. The team owns both sides of the boundary, so the boundary is porous.
Services owned by different teams will be loosely coupled. The team boundary is enforced by the organisational boundary. Changing an interface requires talking to another team. That friction is not a bug. It is the mechanism that keeps coupling low.
The practical consequence: your service boundaries must match your team boundaries. Two teams sharing one service will fight. One team owning four services will collapse them into a distributed monolith within a year. The team boundary and the service boundary must be the same line.
The failure mode: FM2 — Cascading Failures
AT8 pushes toward low coupling because coupling is the substrate on which FM2 propagates. A cascading failure is a failure in one component that triggers a failure in another. Coupling is the mechanism by which one failure becomes the next.
A monolith fails as a unit. A microservice architecture with hidden coupling fails as a cascade. Service A calls service B synchronously. B calls C synchronously. C slows down. B's threads pile up waiting for C. B stops responding. A's threads pile up waiting for B. A stops responding. The user request that reached A originally needed only data that lived in A. The cascade was not required by the business logic. It was required by the coupling.
Independent deployment does not mean independent failure. Two services that never share a repository can still bring each other down at runtime if they call each other synchronously with no timeout, no circuit breaker, no fallback.
Low coupling at the deployment axis is not enough. You need low coupling at the runtime axis too. That means asynchronous communication where possible, timeouts everywhere, circuit breakers on every remote call, and fallbacks that let a service degrade rather than fail.
The signal that tells you this applies to your system
Ask three questions about your last five production releases.
Did any release require coordinating a deployment across more than one team? If yes, your service boundaries and your team boundaries do not match. The services are coupled by shared release cadence.
Did a rollback of one service require a rollback of another? If yes, the two services share state or schema that they should not share. The coupling is at the data layer, invisible to the service diagram.
Did an incident in one service degrade a service that did not call it? If yes, the coupling is transitive and unmapped. Service A did not call service C directly, but they share a database, or a queue, or a downstream dependency that saturated under load. FM2 is running through infrastructure you did not include in your architecture diagram.
Any one of these signals means you have paid for microservices and received a distributed monolith. The remedy is not more services. It is redrawing the boundaries so that a bounded context lives inside a single service, owned by a single team, communicating with other bounded contexts only through explicit contracts that both sides can evolve independently.
The decision, stated in the series' vocabulary
Decision: Split domain X into its own service
Tradeoff: AT8 — choosing low coupling between contexts
and high cohesion within a context
Exposes: FM2 — Cascading Failures at every remote call
Mitigation: Timeouts, circuit breakers, async where the
caller does not need the result, boundary
aligned to team ownership per Conway's Law
If you cannot fill in every line of that block for a service you are about to create, do not create the service. You are not decoupling. You are relocating coupling into a place that is harder to see and more expensive to fix.
The number of services in your architecture is not the metric. The correlation between service boundaries and bounded contexts is the metric. The correlation between service boundaries and team boundaries is the metric. A system with three services and both correlations at one is healthier than a system with thirty services and both correlations at zero.
The full framework treatment — compression blocks, three-level exercises, and the complete AT/FM mapping — is in the Reference Book, Chapter 8 (Architecture Tradeoffs). Free chapter available at computingseries.com/books/ref.