DEV Community

Itay Mendelawy
Itay Mendelawy

Posted on

Breaking Monoliths without Microservices or MFEs

It's easy to stick with monoliths. Our tools are built for it. Think jump-to-definition in your IDE, simply depend on our peers' code, the almighty "single atomic commit that change many things", and, yeah, the sheer joy of running your entire platform with one command—amazing developer experience!

There's just a huge hurdle: that damn project keeps growing! Even in the most meticulously organized and brilliantly designed systems, a small change can trigger a cascading effect. This is the price we pay for relying on the 'bleeding edge' of our peers' code.

And then there are the people. More hires, more opinions, and more frequent changes transform maintaining standards into a political minefield.

Single backend becomes a bunch of microservices! Single frontend turns into several UI apps stitched as microfrontends! Notice a pattern?

We try to solve organizational problems by introducing technical complexities.

What complexities? Integration bottlenecks, for starters. A new feature in a service requires modifying core logic. Orchestrating the platform becomes a nightmare; goodbye single command, hello Docker Compose (or similar tools). Production management gets exponentially harder, as we need more complex monitoring and logging solutions (let's hire more devops!).

Even our developer experience takes a hit. We trade simple-to-debug programmatic APIs for HTTP-API calls between services in the backend or even breaking the frontend bundle to pieces and hoping the app's state/routes remains easy to control.

With more moving parts we add more complexity and eventually hurt ourselves.

If you take one thing from this post, let it be this: you're building a single platform/solution/product for your end-users. Breaking a single unified app to many services which needs to be integrated is, for the most part, an anti-pattern.

With this in mind, I propose a different approach: Composability. Acknowledge that you're building components meant to be integrated seamlessly into a unified product. You're essentially composing a cohesive application, retaining the simplicity and elegance of your initial monolith, with all the benefits of straightforward, safe deployments, programmatic APIs between modules, and optimal performance.
For example, in React, how simple it is to just compose components with JSX in the same app, right?

To help with building composable apps, I use Harmony an open source library that provides a global "API integration slot" registry. Modules simply register their own integration slots (to the global registry) or utilize those provided by others.

This makes modules completely independent. Module is never blocked by integration. Each module integrates itself where needed: API routes in ExpressJS, new browser routes, or even specific places in the UI or backend.

The result? A modular system where modules are acutely aware of their integration points. A single, unified application that's easy to deploy, manage, and scale. And as a developer, you sacrifice nothing in terms of module independence.

Think of Harmony as a powerful yet minimalistic module-system you can take and use it to build for your specific needs. It provides a solid out-of-the-box capabilities (type-support, framework agnostic, inversion-of-control, multi-runtime and more).

Instead of building independent things and struggling to orchestrate them, you're building things that are aware of their role within the larger system.

So, composability offers a pragmatic way to build and scale. It lets you create complex systems and keeping them simple, giving you the best of modularity and maintainability without the drawbacks of services. Harmony, with its "API integration slot" registry, structures dependencies and integrations, simplifying building, deploying, and scaling. Instead of wrestling with independent services, you build a unified whole, piece by piece. Harmony empowers better, faster software development with fewer headaches.

Top comments (0)