Thanks for the feedback. I will try to make this clearer in the article.
While I state later that true decoupling isn't technically possible, it really only makes sense (to me) to attempt it when you've got larger teams split down these lines.
It really comes down to where you want to create the split: in code or on the org chart?
If you've created the split in one place, it will of necessity happen in the other.
If you can avoid the split altogether, then an SPA probably doesn't ever make sense.
This is the organization of the company I work at. Overall I've learned through experience that this decoupled structure is nice in theory and it's useful to have as an option, but it should actually be avoided in practice if at all possible. A developer can end up in a situation where their boss (people manager) really doesn't know about or understand their day-to-day work at all, and then their team lead may be vying for authority over the team with a project manager and product owner, all of whom report in different organizations and have different motivations and incentives.
Why can't you decouple teams form each other with modularity and encapsulation? I never worked in a team, but I could imagine that teams just have some agreements about interfaces and then work independently on a single code base but in a different classes and packages.
I would agree with you that it could be useful for organizational problems but I would resist this as long as possible. In any case, I prefer to not split engineering teams but for practical reasons (e.g. keeping onboarding times into the team reasonable) you are quite forced to do so.
Once your team loses the rapid feedback of "did this break user-facing functionality yes/no?" your reliability and speed of shipping features deteriorates rapidly as now most engineers will start to fear shipping to production.
Ideally, you break the team into subteams and follow the natural fault-lines in the codebase. Most codebases have areas that do not interact much (or not at all) with each other and they lend themselves well to assigning to a specific subteam.
I'm sure there's a point where this breaks also but I haven't reached it yet.
I think that decoupling teams boils down to giving teams complete ownership. And Amazon got parts of it right. It means that your team owns everything it builds. You own the code, you own the testing and you own the operations: you own the product. Various tools are laid at your feet, and you are asked to build.
Clearly, a benefit is that you can move fast. You don't need permissions from someone half a building away to do something. You don't need to touch code that needs another team's approval. There are no committees that decides on global rules. Your team decides on your team's rules.
Like a shared nothing architecture, there's very little that is shared between teams. Teams are often connected only via their service interfaces. Not much else beyond common tooling.
But even their tooling reflects decoupling. Every tool follows the self-service model ("YOU do what you WANT to do with YOUR stuff"). Their deployment system (named Apollo, mentioned in the slides) and their build system, and their many other tooling, all reflect this model.
Cons. What happens is that you might be reinventing the wheel at Amazon. Often. Code reuse is very low across teams. So there's no shared cost of ownership at Amazon, more often than not. It's the complete opposite at Google w.r.t. code reuse. There are many very high-quality libraries at Google that are designed to be shared. Guava (the Java library) is a great example.
Another con. You may not know what you're doing. But as a team you will still build a rickety solution that gets you to a working solution. This is the result of giving a team complete ownership: they'll build what they know with what they have. Amazon is slowly correcting some of these problems by having teams own specific Hard Problems. A good example is storage systems.
And a lack of consistency is a common issue across Amazon. Code quality and conventions fluctuate wildly across teams.
Overall, Amazon has figured out how to decouple things very well.
But on the other hand, doing that just pushes complexity around.
This. In my experience moving to small teams, service-oriented architecture, and semi-open allocation, the underlying problems of coordination were not solved. We had all sorts of issues coordinating API work and being blocked because one team's API was not performing up to par, but they were not fixing it because they had competing priorities. What ultimately helped get us moving again was getting a new engineering lead who had very good overall product judgement and could bang heads to get people on the same track.
If your app is intrinsically decoupled, then obviously small teams and SOA is a good idea. But if your app is inherently interconnected and requires coordination among complex pieces, then you are really choosing your poison either way.
Ultimately, I think the only proven solution for building high quality, complex software systems is to have Steve Jobs or another extremely talented and charismatic BDFL.
The one time I worked in an environment where the work was split up like this, it honestly worked out great. The size of the team (2 FE, 2 BE engineers, PM, designer) must have suited it well. The API boundary was a natural place to divide work. PM and designer would come up with some sketches, we'd all get together in a room, FEs and BEs would say "yep we can build that" or "no that's not gonna work because..." to each feature/page. Then the engineers would collaborate on a shared document to define the API. Once it was fully negotiated, each side could operate pretty independently, and barring a couple complications, it just worked in the end when each side's work was done.
It was a pretty good system, I honestly miss it a lot.
They're talking about the split of programmers, not of concerns. The client-server model is definitely here to stay but having separate groups of people handling each side is a sure way to greatly lower the quality of the product.
Yeah, I have been worried that it could divide our team a bit - front-end vs back-end, which I'm keen to avoid. I like the idea of having a generalist that can help build that bridge. Thanks!
Inverse Conway's Law; organizations are encouraged to create isolated, disconnected teams in order to benefit from modular maintainable code with clear and distinct interfaces.
Doing exactly this at a new organisation I recently joined.
We are treating it as an experiment. Got 2 teams with 5/6 Devs in each sharing the same monorepo. We are using nx.dev as the build tool and it's going pretty well so far.
Different tech stacks too but using nx.dev thats been abstracted away. Allows us to share practices and we've built out the CI/CD and supporting infrastructure on AWS together which has certainly saved duplication of effort. Possibly one more team coming on board too.
If in the future it's not paying off we can always split. Doesn't need to be a forever decision, is how we are viewing it.
Written by someone who's never worked for a large enterprise software company. You cannot apply simply blanket rules like this and expect them to fit every situation. Also, allowing all teams to simply "self organize" pre-supposes that these teams will make smart decisions in their organization, something in my experience which is anything but guaranteed.
Team A strongly depends on Team B's product to the point where their deliverables are impacted by Team B's, how do we collaborate in this case?
Team B depends on Team C's internal platform, how does this teams collaboration differ from Team A and Team B's situation?
Team D has a sub-team working on a highly complex sub-system (real-time ledger for example), this sub-team is growing, how should Team D interact and work with this sub-team?
Team E needs help from the SRE team with reliability and observability issues, how should these teams best work together and collaborate?
My point is, in all these situations, how these teams interact and collaborate will be subtly different based on the situation at hand. A "one size fits all" method of team dynamics simply won't work optimally in every situation. This is what books like Team Topologies are trying to help with.
This problem is mitigated if we assume competent engineering teams on both sides - the away team shouldn’t merge code without proper review of the code by the owner, for one, and the away team should go above and beyond in being diligent about code quality, QA and understanding the codebase to the core before changing it. Thus the away team(s) should consist of the best engineers in the org. That’s my read anyway.
I mean, it makes sense to me: a team should keep its code well-factored but in a single codebase that's integrated and ready to deploy (as one or more deployable units) for as long as is tolerable/possible.
I think a trigger for splitting a module off from a monolithic codebase would be when its value or resource utilization has become disparate enough from the rest that it deserves its own infrastructure and/or its own maintenance crew.
With a lot of small teams, you have each team producing components which are relatively good individually thanks to easy, flat, one to one communication and continuity of means and responsibility. The alternative is some degree of siloing which tends to cause significant overhead which can even result in an organization being completely blocked.
But it's not a perfect approach either. It's really hard to maintain consistency and you tend to have some degree of duplicated effort. This explains partly why AWS is so inconsistent in term of API and also why the console is so slow (and just unusable garbage past a certain size).
And it's not like there is no gradation in between individual teams acting alone and big silos. You could pretty much have something that tries to mix the better of both view, with some kind of lose central authority that is here to enforce stability, SLA, overall architecture and consistency of interfaces (both API and UI) but doesn't dictate which tools mut be used.
Great point! Compartmentalisation is one thing but in large orgs, everyone starts focusing on one metric they need to boost (backlogs or PRs or design mocks) and we have no idea how this will affect other teams. We just have good metrics to show.
While I state later that true decoupling isn't technically possible, it really only makes sense (to me) to attempt it when you've got larger teams split down these lines.
It really comes down to where you want to create the split: in code or on the org chart?
If you've created the split in one place, it will of necessity happen in the other.
If you can avoid the split altogether, then an SPA probably doesn't ever make sense.
reply