Breaking Down the Monolith: Is Microservices the Only Way?

Microservices have proven effective for enterprises to become agile and nimble in their software development and delivery at scale. But it also hurts them in multiple ways.

Ashan Fernando
Bits and Pieces

--

Over the last decade, Microservices have dominated enterprises' go-to architecture style. They have proven effective in scaling development teams, giving them autonomy and the ability to release software rapidly.

If we look deeply, microservice architecture helps establish clear boundaries across teams by breaking the systems into smaller pieces with clear ownership. Since these services interact via APIs, they become loosely coupled, and the team owning the service can develop and release with autonomy. Typically, reusing code across teams is limited to avoid coupling.

The same philosophy can be adopted for frontend applications, where larger frontends are broken down into Microfrontends. However, different frontend teams must share a design system to maintain UI consistency.

But breaking down a Monolith isn’t as easy as it looks. Besides, Microservices and Microfrontends are associated with Several Complexities, which can be costly in the long run.

The Boundary Problem

If you ask a developer, “What is the recommended size of a Microservice?” You may likely get different answers.

The well-known term The Two Pizza Team is the size how Amazon describes it.

But we must accept that it's difficult to define a clear size for a Microservice as it is bound to the domain and dynamics of your teams. As we all know, software evolves rapidly, and you may need to adjust your boundaries over time. When it comes to that, things get complicated as you need to break services further and define new boundaries. Besides, we must sacrifice reusability in code across teams to keep team autonomy.

Unfortunately, the cost of code duplication across the organization is hardly measured since most of the software measurements are bound within a Microservice team.

Also, minimizing sharing kills the organization's collaborative culture. One prominent solution to avoiding these challenges is to design your application according to a composable architectural style.

Composability involves creating software applications from independent, reusable components, each encapsulating its dependencies and distinct functionality. Then, these components (building blocks) can be combined to build complex applications. It’s a fundamental difference to the way we used to develop software applications.

Breaking down the entire application or Microservices into more granular components and working backwards to regroup them allows us to create soft boundaries that can include new components as needed.

To facilitate all these, you may need a toolchain like Bit that also provides the capability to develop, test, deploy, and store components.

But aren’t we already storing the components in Git source control? Before answering the question, let's look at a few source control patterns we follow with Microservices.

Monorepo, Polyrepo

When we break down the Monolith into smaller parts managed by different teams, a typical question is whether to divide these parts into their repository or maintain them within one.

The complexity here is that each team needs autonomy to fully control each service's development lifecycle and deployment, including CI/CD. If you use a single repository (Monorepo style), depending on the modification area, you may need tools that are aware of Monorepo boundaries to build and release it.

On the other hand, if we break the code responsible into multiple repositories (Polyrepo style), we get a clear separation. But sharing even the foundation code requires bundling it into packages. When using packages, you need to update your entire foundation package, even for a smaller change, making it difficult to find its impact. On the other hand, using multiple packages makes things difficult to manage.

Bit solves this in two ways. It introduces a way of storing your components, dependencies, and configurations external to your source control. You get tooling to develop and test multiple components in combination, allowing you to pick and choose the components you need to work on.

The Bit Platform visualizes the relationships between these components and their documentation. Once you modify a component, you can determine its impact.

All your components are stored in collections named scopes in Bit Platform, where you can give permission for contribution.

For example, you can break your Microservices into components and organize them as scopes. The main difference here is that these components can be used by other Microservice teams, where anyone can propose changes to components using change requests.

With these capabilities, you can re-ignite the culture of sharing even across Microservice teams and start measuring its impact.

Culture to Maximize Reuse

Creating a culture of reuse goes beyond reusing code from other teams. Every developer is empowered to practice this approach, which requires them to find existing components before writing new ones. Even when introducing new components, they need to design them meaningfully to allow others to reuse them.

If you are familiar with Packaged Business Capabilities, a culture with reusable components brings it to a more granular level.

Since you can see the dependency graph of components, you can start measuring your digital progress of reuse and the value it adds to the entire organization.

Conclusion

Microservices have revolutionized enterprise agility and scalability in software development. However, the complexity of defining and adjusting boundaries, coupled with the inherent duplication of efforts, often undermines team collaboration and increases maintenance costs. The drive for autonomy can also lead to isolated efforts, dampening the potential for code reuse across the organization.

Therefore, a shift towards composable software architectures is emerging, where applications are built from independent, reusable components. Platforms and tools like Bit facilitate this approach by allowing teams to develop, manage, and refine these components. This addresses the limitations of Microservices and supports a culture of innovation and reuse.

And there you have it. Thanks for reading!

--

--