Microservice architectures have become extremely popular in recent years, and for good reason. When managed properly, they improve scalability, encourage faster development and deployment, and reduce data and domain coupling. Companies of all sizes, from small startups to large enterprises, have migrated their monolithic applications over to microservice and service-oriented architectures.
Making the move from monolith to microservices is a big shift, though. Your team needs to be ready for this change on both the technical and organizational levels. Without careful consideration, a mishandled migration can cause major headaches down the road.
To help ensure your architecture is a success, we’ll share nine microservices best practices for you to consider before, during, and after the move.
Before Migrating
1. Ask “Why microservices?”
First, you should make sure your organization is really served by a microservice architecture.
We’ve written about the pros and cons of Monoliths vs Microservices before. Just because Amazon and Netflix have found microservices valuable doesn’t mean your team will. For certain teams and use cases, monolithic architectures can offer advantages due to their simplicity. Microservices add complexity that may not be worth the cost for your needs.
On the other hand, as many teams have realized, your monolith may be causing major issues. Monoliths can impede scalability because spinning up multiple instances means replicating your whole application. Microservices allow you to target resources where they’re needed and only replicate particular services. Open source technologies like Docker and Kubernetes make this horizontal scaling simple.
Monoliths can also cause organizational challenges. Domain boundaries can get blurry, making it harder to write code without impacting other ongoing work. Coordination issues can slow down iterations as development teams are forced to wait for others to deploy. Testing and releasing can take a long time due to the size of the codebase. Good microservice management encourages decoupling between domains and makes debugging easier. Only small fragments of your overall codebase need to be deployed with each release.
Monoliths also make it difficult to use the right programming languages and tools for each job. If your codebase were in Java, but your data science team wanted to build in Python, it could be difficult to integrate their work or take full advantage of the tools available. Microservices allow you to build each service in whatever language as long as you can communicate through an API.
You need to have a clear rationale for moving to a microservice architecture because you’ll have to share your reasoning broadly with your team. A successful migration requires significant buy-in across the org—see the next tip.
2. Get commitment from the whole organization
Migrations are not easy, especially moving to a microservice architecture. If you spin out one service and your team gives up, all you’ve done is create two monoliths.
To create a truly service-oriented architecture, no single team can undertake this initiative alone. Top-down buy-in is a necessity. The whole organization will need to revamp the entire application, and teams will need to be reoriented around managing their services.
Having clear reasoning that speaks to the team’s needs will be critical for gathering support and maintaining morale throughout the process.
3. Be realistic about the journey
Though you may be excited about the destination—a bright future where teams build at high speed and automation takes care of all your scaling needs—keep in mind that you need to take the journey first. This journey will likely take longer than you think.
Along the way, you’ll run into issues you didn’t expect. Moving to a distributed system is a significant change, and even if some of your team members have experience with microservice architectures, the organization as a whole needs to develop this muscle.
For instance, with each service having its own database, you may need to change how data gets into your data store. For a reliability team, they’ll now have many services to monitor, each with its own dashboards. Teams need to develop processes for defining and updating their services’ APIs. To run effectively, your organization needs to get used to all the changes and downstream effects, and that will take time.
Preparing to Migrate
4. Make a plan and get ready
Get your system ready for your first microservices, and for more to follow. Have a sense of where you’re going to go. It’s better to lay the groundwork ahead of time to make the migration process easier once you’re underway. To help identify some of the hurdles you might run into, check out our previous post about making the move to microservices.
Have a dedicated plan for what you’ll pull out of your monolith first. Understand how turning these portions of your application into microservices will impact upstream and downstream services.
You can start by breaking out one team or domain into its own microservice. The example above of a data science team that wants to work in Python might be a good candidate. You could move their whole stack into a microservice and allow them to take full advantage of available tools and libraries. You could also break your monolith into larger macroservices first, like moving your whole authentication flow into a separate service. This allows the team to define the necessary interfaces at the domain boundaries, saving the more granular work for later.
Also, your DevOps team should build infrastructure to spin up your microservices. Make it easy for engineers to deploy to different environments. Invest in platform tooling and your continuous integration/continuous delivery pipeline. By spending this time up front, you can avoid having to make changes and re-migrate services down the line.
On the other hand, don’t overdo your optimization. Focus on getting the core elements working, and save automation and building a Kubernetes abstraction layer for later.
5. Think about observability and monitoring for APIs
In addition to building services, consider how you can add observability, monitoring, and logging to make it easier to fix issues. Moving to a microservice architecture introduces a new failure mode for your teams. Now, instead of functions calling other functions from within the monolith, communication will happen through API requests, and your team’s software development principles will need to adapt.
Requests can fail due to network connectivity issues. Services can go down. The introduction of latency and asynchronous calls can lead to unexpected behavior. Without proper handling, it will be hard to know what exactly is going wrong and why. Think through these failure modes and add visibility to let you know when they happen. Capture metrics to understand the prevalence of issues.
After Migrating
6. Promote design principles to reduce dependencies
Though you may start with a robust set of independent microservices, it’s easy for unintended dependencies to sneak back in. In the worst case, you could just end up building a distributed monolith, facing the worst of both worlds.
Provide clear guidelines and standards based on best practices to help your team maintain the independence and isolation of your microservices. For instance:
Give each service an independent deployment. This ensures that you aren’t introducing dependencies between services and improves fault tolerance.
Consider using domain-driven design and maintain well-drawn domain boundaries. Martin Fowler’s Bounded Context is a useful model to keep in mind.
Give each service its own backend data store. Otherwise, services may start to rely on databases owned by other teams, causing issues if the schema needs to change.
Use a service mesh to manage requests between your microservices. Use an API gateway to route requests from clients to microservices. These make it easier to manage service endpoints by abstracting them away.
A good rule of thumb: if you have to deploy your microservices in a certain order, they’re not really microservices.
7. Templatize your microservices
Once you have a good idea of what your microservices need, create templates. We’ve explained the benefits of templates and standardization previously.
Creating a new service involves a number of mostly-boilerplate steps developers have to follow. Creating templates will make spinning up new microservices easier for developers and keep them from copy-pasting from old ones. Templates will also automate compliance with your organization’s standards—dockerfile setup, continuous integration/continuous deployment pipeline configuration, health checks—and make it easy for developers to follow those design principles we mentioned in the last tip.
8. Keep track of microservice ownership
For accountability and maintenance, it’s important to know who owns each part of your product. When service ownership is unclear, failures are more likely and more difficult to address. Unintentional product impacts are also more likely to occur as orphaned services are left lingering but still active.
Microservices can move between teams quickly though. It’s easy to lose track if you don’t have a system for maintaining ownership, leading to a thorny problem of untangling who owns each one. Luckily, you’re starting from a clean slate. Make sure each microservice starts with a clear owner and every transfer in ownership is noted. At the bare minimum, you can track this in a spreadsheet.
Check out our previous article on microservice ownership for more info.
9. Invest in a developer portal
Teams often worry about proliferation when building microservices. If not managed properly, developers can lose track of them all, with no one knowing exactly what’s going on, so make sure you have a rigorous way to track your microservices.
You can build a developer portal that makes it easy to spin up new microservices, understand services that already exist, and provide information about your services. This makes it easy to maintain all your services and get visibility into their performance, their owners, and their metadata.
Cortex: the single pane of glass for managing microservices
As you embark on your microservices journey, Cortex can help you access all of the benefits of a service-oriented architecture while avoiding its challenges. Cortex’s Service Catalog can provide a view into all your services that’s simple to maintain, and templated Service Creation and Scorecards make it easy to follow best practices. To see how Cortex can help you, try a free demo today.