12 Ways to Improve Your Monolith Before Transitioning to Microservices

#1 Ensure you know what you’re getting into

A rewrite is never an easy journey, but by moving from monolith to microservices, you are changing more than the way you code; you are changing the company’s operating model. Not only do you have to learn a new, more complex tech stack but management will also need to adjust the work culture and reorganize people into smaller, cross-functional teams.

#2 Make a plan

It takes a lot of preparation to tear down a monolith since the old system must remain operational while the transition is made.

  • Disentangle dependencies within the monolith.
  • Identify the microservices needed.
  • Design data models for the microservices.
  • Develop a method to migrate and sync data between monolith and microservices databases.
  • Design APIs and plan for backward compatibility.
  • Capture the baseline performance of the monolith.
  • Set up goals for the availability and performance of the new system.

#3 Put everything in a monorepo

As you break apart the monolith, a lot of code will be moved away from it and into new microservices. A monorepo helps you keep track of these kinds of changes. In addition, having everything in one place can help you recover from failures more quickly.

#4 Use a shared CI pipeline

During development, you’ll not only be constantly shipping out new microservices but also re-deploying the monolith. The faster and more painless this process is, the more rapidly you can progress. Set up continuous integration and delivery (CI/CD) to test and deploy code automatically.

  • Keep pipelines fast by enabling change-based execution or using a monorepo-aware build tool such as Bazel or Pants. This will make your pipeline more efficient by only running changes on the updated code.
  • Configure multiple promotions, one for each microservice and one more for the monolith. Use these promotions for continuous deployment.

#5 Ensure you have enough testing

Refactoring is much more satisfying and effective when we are sure that the code has no regressions. Automated tests give the confidence to continuously ship out monolith updates.

#6 Install an API Gateway or HTTP Reverse Proxy

As microservices are deployed, you have to segregate incoming traffic. Migrated features are provided by the new services, while the not-yet-ready functionality is served by the monolith.

  • An API gateway lets you forward API calls based on conditions such as authenticated users, cookies, feature flags, or URI patterns.
  • An HTTP reverse proxy does the same but for HTTP requests. In most cases, the monolith implements the UI, so most traffic will go there, at least at first.

#7 Consider the monolith-in-a-box pattern

OK, this one only applies if you plan to use containers or Kubernetes for the microservices. In that case, containerization can help you homogenize your infrastructure. The monolith-in-a-box pattern consists of running the monolith inside a container such as Docker.

  1. Learn about Docker and containers.
  2. Run your monolith in a container.
  3. Develop and run your microservices in a container.
  4. Once the migration is done and you’ve mastered containers, learn about Kubernetes.
  5. As the work progresses, you can scale up the microservices and gradually move traffic to them.

#8 Warm up to changes

It takes time to get used to microservices, so it’s best to start small and warm up to the new paradigm. Leave enough time for everyone to get in the proper mindset, upskill, and learn from mistakes without the pressure of a deadline.

#9 Use feature flags

Feature flags are a software technique for changing the functionality of a system without having to re-deploy it. You can use feature flags to turn on and off portions of the monolith as they are migrated, experiment with alternative configurations, or run A/B testing.

  1. Identify a piece of the monolith’s functionality to migrate to a microservice.
  2. Wrap the functionality with a feature flag. Re-deploy the monolith.
  3. Build and deploy the microservice.
  4. Test the microservice.
  5. Once satisfied, disable the feature on the monolith by switching the feature off.
  6. Repeat until the migration is complete.

#10 Modularize the monolith

If your monolith is a tangle of code, you may very well end up with a tangle of distributedcode once the migration is done. Like tidying up a house before a total renovation, modularizing the monolith is a necessary preparation step.

Strangler fig pattern

In the Strangler Fig pattern, we refactor the monolith from the edge to the center. We chew at the edges, progressively rewriting isolated functionality until the monolith is entirely redone.

Anticorruption layer pattern

You will find that, in some cases, changes in one module propagate into others as you refactor the monolith. To combat this, you can create a translation layer between rapidly-changing modules. This anticorruption layer prevents changes in one module from impacting the rest.

#11 Decouple the data

The superpower microservices give you is the ability to deploy any microservice at any time with little or no coordination with other microservices. This is why data coupling must be avoided at all costs, as it creates dependencies between services. Each microservice must have a private and independent database.

#12 Add observability

The new system must be faster, more performant, and more scalable than the old one. Otherwise, why bother with microservices?

Conclusion

The journey to microservices is never an easy one. But I hope that with these tips, you can save some time and frustration.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Semaphore

Semaphore

Supporting developers with insights and tutorials on delivering good software. · https://semaphoreci.com