Microservices… to use or not to use?

Luis Gomes de Abreu
Nmbrs Tech Blog
Published in
5 min readNov 12, 2019

Microservices are undoubtedly popular, with estimations showing some 63% of enterprises are adopting the architecture. You can hardly turn around without overhearing another conversation about microservices, or seeing another software company contemplating adopting the architecture. But, while microservices certainly has appeal, especially for large organizations undergoing digital transformations or developing cloud-based applications, I firmly believe the architecture isn’t for everyone. That might seem odd coming from someone who championed microservices adoption in my own organization, Nmbrs, but my opinion remains that implementation should heavily depend on growth. The large advantage of microservices lies in scaling and cloud integration, and I’ll use the example of my company’s implementation to explain why.

Outgrowing our architecture

My company develops a Payroll/HR platform, which we launched in 2008 with a small team of just 10 people. We started development using a standard 3-Tier monolithic architecture. Engineering practices were simple with a small number of devs, making it easy to coordinate code branches, commits, product updates, and to measure and manage the impact of change.

By 2019, we had grown to 140 employees delivering 800,000+ payslips each month. Our tiny team of just 3 developers had expanded into 60 people divided into 10 teams. The product was becoming more successful, but with this growth, we were starting to outgrow our architecture. Team and codebase growth meant that work was constantly bottlenecking around the monolithic application. Teams had to coordinate on the same delivery pipeline, which became problematic. If a single team wasn’t ready on time, the entire update would be cancelled.

We needed to return to our roots with smooth, seamless updates. We wanted squads to have control over their development process and codebase. We wanted individual teams to own their own applications. A microservices architecture allowed us to do so by breaking our monolith down into smaller, team-managed pieces.

Adopting Microservices at Nmbrs

It’s easy enough to talk about implementing microservices, but doing so is another question entirely. Changing architecture necessitates a certain number of organizational complexities and impact on the business. Breaking 8 years of monolithic codebase into services was not a simple task.

Our approach was designed to minimize impact on the user experience, while maximizing functionality. To that extent, we began by developing a platform, which we named the Nmbrs Fabric. The Fabric contained communication and structure for microservices, with core functionality such as logging, document storage, tenant management, and identity services.

Rather than immediately extracting modules from the monolith, we started by using new microservices architecture for new features. Our structure enabled the monolith to work side-by-side with new microservices, creating proof of concept without putting our entire structure at risk.

Once we’d proved the architecture was stable, we started extracting modules.

The goal was to make the change without users noticing anything. As I said in my previous post about microservices, “Users don’t care about technical implementation, they just want a seamless user-experience”. To achieve this, we created a front-end widget system to interact with backend microservices.

This perfectly achieved our goals, and users began interacting with microservice features in the new architecture, without realizing a change had happened.

What were the results?

Any architectural change will have major organizational impact. Microservices is no different. At Nmbrs, our new architecture meant shifting development processes and team layout around microservices. Teams worked at different paces, sprint cycles, and update cycles. This allowed teams to become more independent and enabled faster delivery inside their own applications.

It also brought considerable extra complexity. Microservices means adding moving parts, all of which have to work together, even as other parts change. This created extra challenges for QA teams, who have to use integration testing to validate that microservices are working together.

Microservices also adds complications for IT Governance, as permissions, access, and security concerns must be addressed for each independent service. Each service runs its own database, which means we have to query each individual service and combine the results when we want to do data analysis.

Microservices allow faster rollout and delivery for updates, but without careful management and constant integration testing, apps become inefficient, misconfigured, and problematic. Addressing this requires constant work.

So, microservices… always?

With extra costs and complexities in mind, is it always a good idea to move to microservices? No. Instead, you should measure the impact of a growing code base against team productivity. In the beginning, microservices will actually work against you. Added complexity will only pay off when your code base is actually large enough to cause problems for teams. So, I would recommend starting with a simple monolith and, when needed, adapt to microservices.

Finding the sweet spot?

The difficult question is, of course, when are microservices needed. In my opinion, there will never be a perfect moment. If you make the shift too early, the move will backfire. If you move to microservices too late, you’ll have significantly more problems with teams during the migration.

Consider switching to microservices when you begin to observe issues such as missed updates, difficult-to-coordinate teams, and a slow delivery pace. If the impact of change is getting out of control, teams constantly break each other’s code, and delivery is always delayed because of team alignment problems, you might have to switch.

Recommendation — Be ready for it

A good takeaway is to design your monolith in such a way as to enable a migration to microservices. This necessitates isolating modules with few inter-dependencies. Ideally, monolithic modules should already be independent binaries (e.g. Assembly DLLs in .NET), which you can later connect with remote calls. Doing so will ensure that your eventual migration is as pain-free as possible.

In conclusion

As you scale, moving to microservices will become a necessary evil. However, you should see microservices as a solution to a problem. Most importantly, you should only implement the solution it when you have a problem.

--

--

Luis Gomes de Abreu
Nmbrs Tech Blog

Tech entrepreneur who likes to build software products and tackle complex problems