So, you’ve decided to write some microservices but you aren’t sure where to start? Great! You’ve come to the right place. In this article, we’ll examine some of the key patterns and questions to keep in mind when designing and writing microservices.
(Psst. If you’re not sure whether microservices are right for your project, or if you have an existing monolith, check out our article on migrating monoliths to microservices.)
Considerations for Designing and Writing Microservices
Following Domain Driven Design (DDD) when designing your application will help you figure out what the individual microservices should do. The most important thing to remember is that microservices should serve a single business domain, with a well-defined API. Applying DDD will help you figure out what those domains should be and how they should be divided up.
When designing microservices, it’s important to decide in advance how you’ll break up your application. Before you begin, ask yourself these three questions:
- Scalability & Fault Tolerance – Are the scalability and fault tolerance requirements for these two features different?
- Polyglot Codebase – Does this feature require different technology than the others?
- Coupling – Are these features closely intertwined and would they benefit from being in the same service?
Looking at these aspects of your application will not only help you define what your microservices should do but also help you understand how your Dev and Continuous Integration teams work together. More importantly, it reveals what happens to your application when a failure occurs.
Scalability & Fault Tolerance
When creating a distributed system like a microservices application, it’s import to think about how your application will behave when there is a failure. Because microservices are independent processes, you get flexibility in what parts of your application keep functioning if an individual database or microservice is nonfunctional.
One of the greatest advantages of microservices is fine-grained horizontal scalability. By breaking up your application into logical components you can scale each feature of your application individually based on the load.
As with any distributed system, it’s import to keep in mind CAP theorem, which describes the tradeoffs between consistency, availability, and partition tolerance. Depending on how your system is architected, different aspects of CAP are in play. Keeping this in mind when you’re designing your microservices will prevent you from falling victim to the pitfalls distributed applications.
One of the most important consequences of the CAP theorem is eventual consistency. Because your application is distributed, making your entire application aware of a change to the data can take time. Do not allow other services to access the data store of another microservice. This breaks the microservice pattern and compounds the problem of eventual consistency.
Timeouts, retries, and circuit breakers are broad (but very important) topics to consider when designing microservices. Inevitably, one of your microservices will have to interact with another system. To ensure your system stays available, you must implement timeouts and retries to this service. Transient failures are a given when you’re building an application microservices. Circuit breakers prevent your application from attempting requests that are expected to fail.
These patterns reduce latency and allow your application to fail gracefully. It also opens up the possibility of returning a partial response. Timeouts, retries, and circuit breakers are typically offloaded to a sidecar container that dynamically loads the most up to date configuration.
Polyglot Codebase & Service Reuse
Personally, my favorite benefit of microservices is that they provide a clean abstraction for a polyglot code base. This allows your application to be composed of a number of different technologies, so you can pick the best programing language or datastore for each specific microservice.
For example, let’s pretend you’re creating a video service, this allows you to create an account service in Java and a separate video transcoding service in native code. If you create a clear contract exposed by your service, this allows developers to use the best tool for the job, which will increase productivity and reduce the complexity of your application.
Coupling in your application can arise in a number of ways. I prefer to think about it in two different ways: organizational coupling and feature coupling.
- Organizational Coupling
This is how your teams are divided up. If a given set of features are going to be implemented by one team, it’s probably best to have them own those microservices and potentially merge the services together to simplify the design and reduce code complexity. This also works the other way where large sets of features can be implemented by parallel teams.
- Feature Coupling
This is where two features of your application are so intertwined that they might as well be in the same service. This will simplify versioning of the coupled features because they will likely need to be both updated at the same time. It’s also important to think about reuse. Are these two services really independent if they only call on each other? Remember, you can always break up your application into smaller services.
- Organizational Coupling
Think Before You Dive In
Microservices are not a golden ticket to a stable, scalable application, and they’re definitely not for everyone. If you’re getting ready to design a microservice, and you’re confident in the move, we’re here to help. By taking into considering all the aspects we’ve laid out in this article and answering those three questions, you can create a microservice architecture that’s effective.
Don’t be afraid to experiment and change your design as you learn more about your application and the failures you experience.
Not sure what to do next? Take the DevOps Maturity Assessment to evaluate your organization across five DevOps domains.
Writer: Bryan Absher
Bryan Absher is a Software Engineer who is passionate about new and old technology. He is currently working on large scale distributed applications and single page web apps in the Pacific Northwest.
Fun fact: Bryan has a cat and will dance your pants off.