Engineering Culture

Microservices: The Org Problem, Not The Code

Deployments are slow, teams are entangled. Your monolith's got problems. But breaking it apart into microservices might just be the worst idea you ever had.

A chaotic diagram of interconnected boxes representing services, with arrows pointing in multiple confusing directions.

Key Takeaways

  • Microservices adoption often fails because it's treated as a technical problem, not an organizational one. Conway's Law is paramount.
  • Amazon's adoption of microservices was driven by the need to decouple teams and scale organizational velocity, not primarily for technical scaling.
  • Drawing service boundaries around technical concerns (e.g., 'auth service') instead of business capabilities leads to distributed monoliths and increased complexity.

The server whirred, a lonely sentinel in a data center that time forgot.

Microservices. Remember that golden age? Developers, tired of the monolithic beast, dreamed of sleek, independent services, each doing one thing well. The promise was agility. The reality? Often, a tangled mess worse than what they started with. Every failed microservices adoption I’ve seen, and trust me, that’s a long list, made the same colossal mistake: they treated microservices as a technology problem instead of an organizational one. The tech? That’s the easy bit. The rest? That’s where the actual pain resides.

Here’s how the script usually plays out. Your monolith is a tangled ball of yarn. Deployments crawl. Navigating the codebase feels like spelunking without a headlamp. Then, a wise senior engineer pipes up, “Let’s break it apart into services!” Everyone nods, blinded by the shiny allure of independence. Six months later, things haven’t just failed to improve; they’ve actively degraded. Services are either too tiny to be useful or so massive they’re just miniature monoliths. Nobody can agree on where the boundaries should lie. That simple feature you wanted? Now requires orchestrating changes across three different repos. A bug that used to be a quick twenty-minute hunt? Suddenly a two-hour odyssey because it hops across service boundaries. Deployments are more frequent, sure, but each one feels like a gamble. Your team’s working harder, yet achieving less. And they blame the technology. Of course they do. The technology isn’t the villain. Microservices failed because the team treated decomposing their system as a purely technical decision, completely ignoring the organizational quagmire they were actually supposed to be solving. You can’t just divorce your architecture from your team structure. Conway’s Law isn’t a suggestion; it’s a fundamental truth.

Think back to Amazon. The early 2000s. Jeff Bezos, in his infinite wisdom, issued a decree: all teams must expose their data and functionality via service interfaces. Inter-process communication? Strictly through these interfaces. No other way. Deviate, and face the firing squad. He wasn’t kidding.

The problem Bezos was tackling wasn’t technical. Amazon had grown into a sprawling behemoth. Teams were so deeply intertwined that a single deployment required a cascade of synchronizations. Team A couldn’t deploy without Team B’s blessing, which needed sign-off from Team C, who owed a favor to Team D. Every change was a diplomatic negotiation. Releases were war councils.

The coupling between teams was actively strangling the organization’s ability to move at speed. Services were the enforced solution. They mandated a contract between teams. If Team A owned Service A and Team B owned Service B, communicating solely through a defined API, then Team A could refactor the innards of Service A without needing Team B’s explicit permission. Team B could deploy their service on their own timetable. The technical boundary acted as a bulwark for organizational autonomy.

This is the critical miss that sinks most microservice adoptions. Services aren’t primarily a scaling mechanism for technology. They are a scaling mechanism for teams. The technical perks—independent deployment, tech stack flexibility, fault isolation—are merely pleasant side effects of the core organizational benefit: team autonomy. Without the organizational restructuring to enable that autonomy, you’re left with all the pain of distributed systems and none of the actual advantages.

The Unvarnished Truth About Distributed Systems

A monolith, for all its warts and wrinkles, possesses inherent qualities that distributed systems simply cannot replicate. A function call within a monolith is a thing of beauty: reliable. It either works or it throws an exception. It’s lightning fast, completing in mere microseconds. Best of all, it participates in the same database transaction. If the whole shebang needs to be rolled back, it’s a clean, atomic operation.

A network call between services? That’s a different beast. It might work. It might fail. It might succeed on the server side but die in transit before the response gets back. It could time out, leaving you with a gaping hole of uncertainty about whether the remote operation even happened. It’s comparatively glacial in speed. And crucially, it crosses transaction boundaries. If something goes sideways after the call succeeds, you’re left with consistency nightmares that a simple rollback can’t fix.

This isn’t some minor implementation detail to be worked around. It’s a foundational reality of distributed systems, eloquently captured by the Fallacies of Distributed Computing, penned by Peter Deutsch way back in 1994. The industry, it seems, has a penchant for rediscovering these truths periodically.

The network is not reliable. Latency is not zero. Bandwidth is not infinite. The network is not secure. Topology changes. There is not one administrator. Transport cost is not zero. The network is not homogeneous.

Every single service boundary you introduce is a new battleground where these fallacies come to life. Every network call is a fresh opportunity for latency, failure, and consistency issues that are utterly absent within a monolith. The real question, the one most teams conveniently skip, is whether the organizational gains derived from that boundary truly justify the inherent distributed systems cost of maintaining it.

For a small team of eight wrestling with a single product, the answer is almost invariably no. The most common pitfall? Drawing service boundaries around technical concerns rather than business domains. They churn out an “auth service,” a “notification service,” a “user service,” a “payment service”—all dictated by technical function, not by cohesive business capability. This creates dependencies that mimic the very entanglement microservices were meant to solve, just now spread across a network.

Why Did They Build a “Notification Service” Anyway?

This obsession with technical categories rather than business capabilities is a smoking gun. Imagine a scenario where a user registers, makes a payment, and receives a confirmation email. In a poorly designed microservice architecture, this might involve invoking: User Service -> Payment Service -> Notification Service. Each step is a network hop, a potential point of failure, and a delay. The underlying business process is fractured across multiple, independently deployable — and independently fragile — components.

This isn’t elegance. It’s complexity for complexity’s sake. It’s the illusion of progress, masked by distributed jargon.

Amazon’s success wasn’t about the act of creating services; it was about the reason they created them: to decouple teams and enable independent velocity. If your organization isn’t structured to benefit from this team autonomy, imposing microservices is like trying to solve a leaky faucet by demolishing your house. You get a much bigger problem.

So, What’s the Alternative to a Monolith That Won’t Break?

Forget the trendy jargon. Think about your organization. Are your teams structured around business capabilities? If Team X owns the entire user lifecycle – from registration to profile management to preferences – then a single, well-factored module within a monolith dedicated to that capability makes perfect sense. If that module grows too large or becomes a bottleneck for unrelated work, then you might consider extracting it, but as a service that maps directly to a business domain, not a technical function. This is often called a modular monolith or service-oriented monolith, and it’s a far more sensible starting point for most organizations.

The technology choices – REST APIs, gRPC, message queues – are merely tools. The decision of when and where to draw a boundary is an organizational one, rooted in how your teams collaborate and how your business operates. Until that’s understood, you’re just building a distributed monolith, and nobody wins.


🧬 Related Insights

Frequently Asked Questions

What does “Conway’s Law” mean for microservices? Conway’s Law states that organizations design systems that mirror their communication structures. For microservices, this means if your teams are siloed, your services will likely be too, creating dependency hell. If teams are organized around business capabilities, their services will likely align with those capabilities.

Will this mean I have to rewrite my entire system? Not necessarily. The key is to understand your organizational structure and draw new boundaries based on business capabilities, not just technical concerns. Often, this involves refactoring within a monolith before considering new service extraction.

Is a monolith always better than microservices? A monolith isn’t inherently better, but it’s often a more sensible starting point. Microservices add significant operational and developmental complexity. The benefits of microservices only outweigh these costs when you have a large, complex organization that requires extreme team autonomy and parallel development, and you’ve structured your teams accordingly.

Written by
DevTools Feed Editorial Team

Curated insights and analysis from the editorial team.

Frequently asked questions

What does "Conway's Law" mean for microservices?
Conway's Law states that organizations design systems that mirror their communication structures. For microservices, this means if your teams are siloed, your services will likely be too, creating dependency hell. If teams are organized around business capabilities, their services will likely align with those capabilities.
Will this mean I have to rewrite my entire system?
Not necessarily. The key is to understand your organizational structure and draw new boundaries based on business capabilities, not just technical concerns. Often, this involves refactoring within a monolith before considering new service extraction.
Is a monolith always better than microservices?
A monolith isn't inherently better, but it's often a more sensible starting point. Microservices add significant operational and developmental complexity. The benefits of microservices only outweigh these costs when you have a large, complex organization that requires extreme team autonomy and parallel development, and you've structured your teams accordingly.

Worth sharing?

Get the best Developer Tools stories of the week in your inbox — no noise, no spam.

Originally reported by dev.to

Stay in the loop

The week's most important stories from DevTools Feed, delivered once a week.