Coupling
Concept
How much changing one part of a system forces you to change another part — the measure of whether the lines you drew between pieces actually hold.
Why it exists
Past a certain size, changing a program starts to feel dangerous. You edit one line of notification copy and the checkout screen breaks, and until someone opens the code nobody can say why. At Pagedeck, Theo once tidied up the document-storage code and notifications stopped working entirely. The two features had nothing to do with each other on screen. The notification code was reading the database table that document storage owned.
When that keeps happening, teams get defensive. They leave code they could fix alone and bolt each new feature onto the side of the old one, which adds more entanglement. And there was no way to raise it as a problem: "this code is kind of complicated" doesn't win you an extra week in a planning meeting.
Coupling is the word that puts a scale under "kind of complicated." It ignores how much code there is and how hard the code is, isolating one thing only — the connections between pieces. That narrowness is what makes design conversations stop being arguments about taste. Instead of debating which structure is nicer, you count how many places have to be opened to change one behavior. Three files is a different conversation from twelve, and both sides of the table can see the same number.
How it works
Coupling comes down to how specific the information passing between two pieces is. The more one piece knows about the other's internals, the tighter the coupling. The less it knows beyond an agreed set of values, the looser.
The same two features can be wired several ways. From loosest to tightest:
- Publish an event — the document module announces that a document was saved and has no idea who picks it up. This is what event-driven architecture does. Notifications can be down and the save still completes.
- Call through an agreed entry point — the caller goes through the API (application programming interface) the document module exposes, meaning the set of calls it has promised to keep working. Keep the shape of those calls and everything behind them is free to change.
- Call an internal function directly — reaching past the promise into a function nobody agreed to keep stable. Rename it or change its arguments and the caller breaks with it.
- Read the other side's data directly — notification code queries the document table itself. Renaming a single column stops notifications, and whoever owns documents has no idea anyone was reading their table.
- Share global state — both pieces read and write the same variable. There's no longer any way to trace when a value changed or who changed it.
An appliance and a wall socket make the shape obvious. Match the plug and you can run a vacuum without knowing how the wiring behind the wall is laid out, and rewiring the wall doesn't affect the vacuum. Solder the vacuum's cable straight to the wiring and it works fine today — but changing either one now means opening the wall.
Where it shows up
It gets used both in architecture decisions and in everyday work.
Choosing a structure comes first. A monolith puts everything in one deployable unit, so internal calls are direct and fast to write, and coupling climbs easily. Microservices split by feature and deploy separately, which forces coupling down at the cost of running deployment and monitoring once per service. A modular monolith ships as one unit but blocks modules from calling anything but each other's declared entry points, aiming at the middle.
It comes up constantly in code review. When a small change touches twelve files, there's usually entanglement at that spot. It also sets the order for refactoring — reshaping code without changing what it does. You work through the places that get edited often, tightest coupling first. Deferred cleanup that slowly taxes your speed is called technical debt, and this is generally where its interest is most expensive.
Tests give a quieter signal. If writing a unit test for one function requires standing up a database and a payment provider, that function is already tied to all of it. The feeling that something is hard to test is usually the earliest warning about coupling anyone gets, and it arrives long before the structure visibly hurts anyone. A team that notices it early pays for one afternoon of rework; a team that ignores it pays for a rewrite later.
How it sounds at work
"Coupling is high here, so I can't fix just that piece."
A report that the scope is wider than expected, and usually a request to reset the schedule.
"Notifications are reading the documents table directly. Let's move it to an event."
A concrete proposal to convert case 4 into case 1.
"With the current structure we can't deploy checkout on its own."
Coupling has fused the deployment units together, so even a small fix has to ride a full release.
At Pagedeck the word travels alongside scheduling. Mia budgets three days to adjust notification copy, Theo answers that the work actually reaches into document storage, and coupling is what explains the gap. It isn't a metric anybody charts — it's a way to describe scope, and to show that the difference between three days and ten comes from structure rather than from anyone being slow.
That's also why it never functions as a way to refuse a request. It sets up a choice: this takes that long under the current structure, and untangling it once makes every similar change a one-day job.
What people get wrong
The most common misreading is that lower is always better. High coupling causes problems, so driving it toward zero sounds like the goal. But every step down costs an intermediate layer and another agreement between pieces, which means more code and a harder path to follow. Split a two-screen product into six services and tracing one feature means opening twenty files. The target isn't zero. It's keeping things that change together close and things that change separately apart.
The other belief worth dropping is that splitting things up lowers coupling by itself. Carve a system into five services that all read and write the same database table and changing that table means five teams deploying at once. The deployment units multiplied while the entanglement stayed, which is why this gets called a distributed monolith. It's worse than the monolith it came from: calls that used to be local are now network calls, so there are more places to fail and nothing was gained.
Easily confused with
| Term | What it looks at | How it differs |
|---|---|---|
| Cohesion | How much the code inside one module belongs to a single job | It looks inward; coupling looks at the space between modules. The two usually move together — draw the boundary well and cohesion rises while coupling falls |
Where to go next
- Software architecture
see which structural choices this scale is used to judge
- Cohesion
the paired measure, and boundaries only make sense when you read both
Last updated 2026-09-16