Hi, Pablo here
Conway's Law cuts both ways
Published: 2026-09-28
This article is a small reflection on a useful way to look at Conway's Law that I think many people working in software have not observed. I'll assume you're familiar with Conway's Law. If not, here are some nice explainers so you can get on the same page:
- The original paper: How Do Committees invent? by Melvin E. Conway
- Conway's Law by Martin Fowler
So, to the point: most of the time I bump into someone bringing up Conway's Law, they do so to highlight how the organizational and communication structure is impacting the systems that get built. "We should split this team into two so one takes service A, the other takes service B and they can work independently". Or, "it's pointless that we all try to build on a monolith if the three teams we have are in different time zones, have different managers and barely talk with each other". I also find it's used more retrospectively than proactively. That is: more as an explanation of how a system came to be the way it is (and usually used when it's fucky), rather than a tool to try to influence how a system ends up being. Thoughtworks did introduce the Inverse Conway Maneuver, which at least tries to leverage the law as a tool of change instead of an a posteriori explainer. Plus: I've never met anyone in real life who was familiar with the inverse maneuver.
Where I would like to bring some attention is to the idea of putting it the other way around, in the direction of the law: looking at how the code/system changes the org/comms. And to try to use this as a way to influence the outcomes of the org, not as a postmortem explanation.
Let me discuss some examples.
Enforcing boundary contracts
In large enough engineering orgs, you end up having Alice's service depend on Bob's public interface. When these contracts are purely internal, Bob ends up introducing unexpected breaking changes more often than Alice would like, for a variety of reasons. With the consequences being only internal and attributable to reasonable human error, I've noticed that serial contract breakers like Bob only get called out if their breakages lead to serious outages in a very immediate and direct way.
In one specific instance, I witnessed this setup, which I found interesting: Alice herself added some automated
CI checks in Bob's repo that enforced what she needed out of his public interface, set up in a way that wouldn't
allow Bob to go to production while breaking that. Furthermore, she leveraged CODEOWNERS to set the
repo up so that only her review was valid for these CI checks.
Bob would have to align with Alice on every breaking change. This resulted in some behaviour changes:
-
Bob was not deploying breaking changes on his own anymore. Skipping the CI and
CODEOWNERSfences would have been too daring. - Bob started to think harder about how to execute his work without breaking his contracts with Alice.
- Whenever Bob knew he had to break them, he would seek alignment with Alice as early as possible, for he knew she was now a bottleneck to his own execution.
- Bob started to care about having a smaller public surface, and would push Alice hard to include in the automated checks only the strict public surface she depended on, and not more.
The monolith that wanted to couple
In another instance, I worked in a small team that revolved around a single repo. The repo itself held a monolith, which was an intentional architectural decision by the group's technical leader. But another intentional decision by him was that different modules of that monolith had to stay decoupled from each other: he wanted to push harder for a modular monolith, hoping to avoid the dangers of microservices while reaping the advantages of a single monolith and of decoupling at the same time.
There were several tricks in his toolbelt to ensure this wasn't broken. One of them was to literally prevent imports across modules. Each module could only talk to others through shared infra or explicitly defined public APIs. CI checkers would enforce this hard, flagging PRs that tried to skip it.
A few consequences of this:
- The decoupling-by-decree did a decent job at keeping modules decoupled, which gave the engineers working in different corners of the monolith good independence to work without being blocked by others. Large reorgs and refactors that could be done strictly within the private part of modules mostly happened without other colleagues even having to be warned.
- But living under the same repo umbrella, testing and many other integration tasks were still shared among the team, so if you somehow still managed to break someone else's turf, you noticed.
- The strict no-coupling checks sometimes led to situations where it was extremely tempting to remove the rules because it would have made our lives so much easier. Those situations were hints at some shortcoming in the wider architecture of the monolith, and led to some very thoughtful whiteboard sessions that helped shape good ways to achieve what we wanted without letting the modules talk to each other.
The keys to the secrets
Another org was struggling with a sprawl of SaaS and infra services being hired left and right. The org had grown from a small team to multiple independent teams, and each team was just going around shopping for whatever cloud tooling was useful for their work. It quickly grew into a mess of duplicated services, where common needs such as observability, documentation or even databases were being served by two or three tools where one would have been enough.
The org was lucky enough that at least Git and their pipelines were still centralized in a single place, so the following single change was made: one single engineering team, led by a very assertive manager, was put in charge of the secrets manager that was used by their CI/CD pipelines. You could only go to production through it, and only this manager could actually edit the contents of the vaults to include whatever tokens/keys/secrets your tooling needed.
Once this was decided, the first impact was quick: the sprawl stopped because, if you wanted another tool, you had to convince that manager, which was anything but trivial. The second effect came in slowly, as certain tools were promoted over others and deprecation dates were set under the threat of secrets disappearing from the vaults. Initially, this setup was overwhelming for the team sitting on top of the secrets manager, since they suddenly became a bottleneck for pretty much every other team in the org. But the pressure incentivized everyone to adapt: the gatekeeping team quickly standardized all their business-as-usual to make it as fast and scalable as possible. The teams depending on it quickly learned to plan ahead when secrets management was part of some line of work, and developed the habit of using what they had available in the org instead of just picking any shiny SaaS that was walking by.
The take away
That's just a few. I could add more, and you would suddenly get bored because the pattern becomes obvious. The overarching story to take away: you make some hard rule in code. Because code is stubborn, people adapt around it and so your organization and how people work change as a result.
As someone who has both technical and managerial responsibilities, I find this mindset of changing the org via the code interesting and useful. I will often find myself thinking: which technical decision will drive the behaviour that I want to see in my org?
Is the solution to flip-flopping, mind-changing product owners to make messages containing the words "urgent", "change" and "priority" undeliverable in Slack?