I think Ian is not seeing the reason software architecture ends up matching organizational structure.

He's right that engineers can imagine architectures that don't reflect org structure. I mean, of course they can.

However, to have that imagined architecture be implemented, you have to go and talk with whoever controls the parts you don't control. Even if they are totally happy and willing and able to make the changes you want, this step of communicating with them, defining the new cross-team responsibilities, defining interfaces, all the tasks around actually doing this cross team work, come at a much higher cost than intra-team work. Within a team you have more communication bandwidth, you know the people and how decisions are made, and all that means that within your team you can move much more quickly.

Now, people will do the following estimate, whether explicit or implicit to their thinking: is goodness(architecture1) > goodness(architecture2)?

Conway's law comes out of the time locality of that attempt to decide 'what is the best architecture', combined with what is necessarily almost complete uncertainty when trying to estimate future costs and benefits.

Since cost(architecture_internal_only) < cost(architecture_cross_org) whenever the technical advantage of cross_org is less than the added costs of cross organization coordination, there will be many decisions made in favor of internal_only. In fact, whenever there is no clear technical advantage to one or the other, internal_only will always be a better decision.

This is where locality kicks in. Every internal_only decision increases the cost difference in future decisions architecture decisions between internal_only and cross_org, in favor of internal_only.

For example, lets say you are building a web browser. Your team (team A) is working on javascript. Another team (team B) is working on a rendering engine. Both require parsing text based languages, so you might decide to work together to standardize on a common tokenization/lexing engine both teams can use. However, doing that would be quite painful compared to both teams taking the shortest path to solving their own lexing problem. It's not even clear that in the long run it would be better to standardize. So both teams build a Lexer. Now, it so happens that team B has someone with a natural talent for writing Lexers, and their lexer is just plain better. Of course, team A hasn't been sitting around for 2 years.

Team A has a requirement to support the newest version of javascript, and that means some changes to how the parser works. Should team A adopt the team B lexer, which is better in every measurable way, or just update their current parser? Well, the cost of using the team B lexer is now HUGE, since it would mean digging out the current lexer. Maybe the team B parser uses multiple passes, where team A has lexing integrated into the parser. The specifics aren't super important, it would probably be insane to take a 2 week project and turn it into a 3 month project just to avoid the duplication. Not to mention, they have 2 years of getting the current solution working well in the real world. Dozens and dozens of real world crap has been quietly accounted for and dealt with. There aren't any bugs reported against the current solution. Changing is more expensive and will potentially introduce bugs. So now both teams just keep going with their own lexing strategies forever, it will never be the right decision to remove this reflection of the organizational structure.

In year 3 the teams get reshuffled, and one team is now responsible for all the parsing. They inherit both the HTML parser and the JS parser. What do you think? How long will it be before they see how nice it would be to unify the parsers? How would you feel if you were working on both, wouldn't you feel the urge to 'clean this up'?

Now, what if early on, you had decided to in fact do the 'one lexer to rule them all'. You may have discovered in 2 years that the tasks of parsing HTML and JS are just fundamentally so different that it was hopeless to try to share functionality in this way. The JS parsing is hopelessly slow compared to competitors, because the lexer needs to deal with tons of insanity in real world HTML. Or maybe it works out great? It's just too hard to make a reasonable guess up front to justify choosing a more expensive, longer plan.