Throughout my career, transitioning between CTO roles and, more recently, focusing purely on distributed systems architecture and high-performance engineering, I've seen many architectural patterns rise and fall. But few have caused as much silent damage to company bottom lines as the premature adoption of microservices.
Over the last decade, the industry bought into the idea that, in order to scale, you needed to split your system into dozens (or hundreds) of independent services. The practical result I find in most companies? The creation of the dreaded "Distributed Monolith."
The Anatomy of Waste: Networks vs. Memory
The hard truth we need to face with maturity is that microservices primarily solve problems of organizational scale (Conway's Law), not necessarily performance. If your engineering team isn't the size of Netflix or Uber, prematurely fragmenting your codebase is shooting yourself in the foot.
Technically, what happens when we break down a monolith without the proper domain boundaries? We trade extremely fast and cheap local function calls (resolved in the processor's L1/L2 Cache) for slow and expensive network calls (TCP/IP).
We start spending an absurd amount of computational time on constant JSON serialization and deserialization, and the AWS bill explodes with internal traffic costs (egress/ingress) between Availability Zones (AZs). You haven't scaled your application; you've merely added network latency and infrastructure complexity.
The Return of the Modular Monolith
True seniority in software engineering isn't about mastering the most complex architecture of the moment, but having the wisdom to know when not to use it. That's why the Modular Monolith has consolidated itself as the initial gold standard for new projects and restructurings.
In a well-designed Modular Monolith (and languages with strong type systems and strict scope control, like Rust, shine absurdly well here), you maintain the logical separation of domains. Modules are independent, business rules are isolated, but the deployment is singular. Communication between modules goes back to being in-memory. Performance skyrockets. AWS costs plummet. The team's cognitive overload disappears.
It's exactly the difficulty of debugging this invisible latency between poorly divided services that motivated me to adopt the 'Build in Public' approach to create a DevTools Chrome extension. I'm developing a tool focused on giving engineers real visibility into payloads and client-side bottlenecks, saving hours of troubleshooting in complex architectures
.
Pragmatism as a Metric
Software engineering is a continuous exercise in managing trade-offs. If your current architecture is consuming financial resources that should go towards the product (or into the employees' pockets) just to maintain "vanity complexity", it's time to rethink. Having the courage to lead a rollback to a well-structured monolith isn't a step backward; it's the pinnacle of technical pragmatism.
Top comments (0)