Beer & Servers Don't Mix

The “We Have a Team for That” Fallacy

Or: How We Built Organizational Silos and Called It Specialization

There’s a peculiar disease that infects growing software companies. It starts innocently enough — you hire specialists because you want experts. Before you know it, you’ve got a team for everything: the QA team, the Operations team, the Database team, the API team, the Team-That-Knows-Where-The-Bodies-Are-Buried team. And suddenly, getting anything done requires more coordination meetings than a royal wedding.

As Gene Kim put it in The Phoenix Project: “In any value stream, the bottleneck is the constraint. When work has to wait for another team, that team becomes your constraint.” Here’s the thing — we’ve created these constraints ourselves. Every team boundary we draw is a potential bottleneck. Every handoff is a queue. Every “we need to wait for the other team” is money burning while we watch.

The Evolution of Dysfunction

Let me take you on a journey through the stages of organizational grief — I mean growth — that I’ve witnessed across continents, from my early days in Australia to here in Bangkok where the heat isn’t just from the weather, but from the friction between teams.

Stage 1: The Testing Team Bottleneck

Remember when we thought having a dedicated QA team was the height of professionalism? We’d throw code over the wall like medieval siege engineers, then act surprised when bugs came flying back. Most companies have moved past this particular flavor of dysfunction — cross-functional teams are table stakes now. If you’re still doing this, well, you’re playing checkers while everyone else has moved on to chess.

Stage 2: The System Teams Trap

Here’s where it gets interesting. You’ve got your cross-functional teams humming along nicely, and then someone notices that multiple teams need to touch the same systems. “I know,” says some well-meaning executive, “let’s create a team that owns each critical system!”

I once worked at a company where we had a team that owned the Pricing API. Sounds reasonable, right? Pricing is complex, it’s critical, surely it needs dedicated ownership. The problem? Every product initiative needed pricing changes. We’d essentially created a tollbooth on the highway to production.

The solution they came up with was even more spectacular: give that team its own Product Owner. So now we had one PO prioritizing work that affected half the other POs in the company.

The InnerSource Mirage

“Why don’t other teams just contribute to the Pricing API?” I suggested, channeling my inner open-source evangelist. “The owning team can review the changes.”

Now, to be fair, this InnerSource model had actually worked brilliantly for most of our systems. Authentication service? Teams were submitting PRs left and right. Notification system? Contributions flowing smoothly. It’s a solid next step after you’ve moved to cross-functional teams — let teams contribute to the systems they depend on rather than waiting in a priority queue.

But the Pricing API? The pushback was swift and predictable: “It’s too complex. Other engineers won’t understand it.”

And here’s the thing — they were right. Not every system is a good candidate for the InnerSource model.

This is where we need to talk about complexity, and I’m going to get a bit philosophical here. Bear with me.

Understanding Complexity: A DDD Perspective

Domain-Driven Design makes a crucial distinction that most organizations miss: not all complexity is created equal. You’ve got your core domains — the stuff that makes your company special, your secret sauce, your reason for existing. Then you’ve got your generic and support domains — the stuff everyone needs but nobody brags about at conferences.

Look at this matrix and it becomes crystal clear. The vertical axis is business logic complexity — how hard is this thing to understand? The horizontal axis is business differentiation — how much does this set you apart from competitors?

Core domains (top right) are both complex AND differentiating. Your pricing engine, your recommendation algorithm, your secret sauce. These are legitimately hard problems that make you special. These might actually need dedicated teams.

But here’s the nuance most people miss: not every core domain needs to be a complicated subsystem with its own team. Some core domains can be owned by feature teams. But if every team needs pricing changes every sprint, and the domain model is genuinely complex with hundreds of edge cases and regional variations? That’s when you might need a dedicated team.

Supporting domains (bottom right) differentiate you but aren’t that complex. Maybe you have a unique way of handling customer support tickets, but it’s not rocket science. These are perfect for InnerSource — important enough to matter, simple enough for any engineer to contribute.

Generic/supporting gray area (bottom left) are neither complex nor differentiating. Your authentication, your CRUD operations, your basic reporting. If you have dedicated teams for these, you’re doing it wrong. Buy it, open-source it, or let anyone contribute to it.

The Generic domains (top left)? That’s where things get tricky. Complex but not differentiating — like a complicated legacy system that does basic stuff in a convoluted way. These are your technical debt magnets, and honestly, you should probably be simplifying or replacing them, not building teams around them.

Here’s the thing: if your authentication system is your competitive advantage, you’re in trouble — unless you’re Auth0 or another cloud auth provider where authentication literally IS your product. That’s a solved problem for the rest of us. But your pricing engine? Your recommendation algorithm? Your unique way of solving customer problems? That’s where complexity belongs.

As the chef Ferran Adrià once said about molecular gastronomy: “The simpler the technique, the more complex the dish can be. The more complex the technique, the simpler the dish must be.” In software terms: your supporting domains should be simple so your core domains can be complex.

Team Topologies takes this further and acknowledges that sometimes you need “complicated-subsystem teams.” Sometimes, the complexity is real and necessary, not accidental.

The Spotify Model: Embedding Problems

Spotify tried to square this circle with embedded engineers — specialists from complicated-subsystem teams who join other teams temporarily. Here at Agoda, we ended up going down this same path. You know what we got? Engineers with two managers, two sets of priorities, and twice the meetings.

As Matthew 6:24 wisely noted: “No one can serve two masters.” This wisdom is literally thousands of years old, yet here we are in 2025, with our Agile certifications and management frameworks, making the exact same mistake and calling it innovation.

But here’s the thing — despite all its flaws, it was still better than the alternatives we’d tried. At least work was getting done. At least teams weren’t completely blocked waiting for the Pricing team’s sprint to start. It’s not about finding the perfect solution; it’s about choosing which problems you’re willing to live with.

The Lesser of Evils

Here’s the uncomfortable truth: there’s no best practice here. There’s only context and tradeoffs. Every organizational structure is wrong; some are just less wrong for your specific situation.

The key questions you need to ask:

Is this really a core domain that needs specialized ownership?Can we make the interfaces simple enough for InnerSource to work?What’s the actual cost of coordination versus the cost of duplication?Are we optimizing for speed, quality, or innovation? (Pick two, if you’re lucky)

Moving Forward: Conscious Choices

The next time someone says “we need a team for that,” stop and think about where you are in the evolution. Each step we’ve taken as an industry made sense:

Functional teams gave us deep expertise but created silosCross-functional teams broke down silos but created system coordination problemsInnerSource solved coordination for simple systems but failed for complex domainsSystem teams protected complex domains but became bottlenecksEmbedded engineers unblocked teams but created dual-reporting nightmaresEach solution solved the previous problem and created a new one. That’s not failure — that’s evolution. Team Topologies got this right: there’s no universal answer, only context-appropriate patterns. The wisdom isn’t in finding the perfect structure; it’s in understanding which problems you’re solving and which ones you’re creating.

The Bottom Line

We’ve turned the search for team structure into a quest for a silver bullet that doesn’t exist. Every organizational pattern is a tradeoff. Every boundary you draw enables something and constrains something else.

The “we have a team for that” fallacy isn’t really about having too many teams — it’s about not recognizing that team boundaries are design decisions with consequences. Just like in software architecture, the choices that make sense at one scale become problems at another. The monolith that got you to product-market fit becomes the bottleneck at scale. The microservices that enabled scaling become the coordination nightmare.

So the next time you’re in a meeting where someone suggests creating a new team to solve a problem, ask: What problem did our current structure solve? What problem is it now creating? What new problem will this change introduce?

Because in the end, we’re not solving problems — we’re just choosing which problems we prefer to live with.

Now if you’ll excuse me, I need to coordinate with three different teams to deploy a one-line configuration change. But hey, at least we have clear ownership boundaries.