What are Microservices?
Applications are commonly grouped under the umbrellas of monolithic or distributed. In simple terms a monolithic application refers to a single code base that contains all the functionality for a given product offering and is deployed into production as a single entity. In this article we will expand on the concept of microservices, which are an architectural variant of a distributed application architecture (a product comprised of multiple separate applications working together to produce business results). In a microservices architecture there are multiple separate smaller separately deployable stand-alone applications (services) which together form the customer’s experience of the product.
For historical context microservices are a variant of the service-oriented architecture (SOA) that started to emerge in ~1998. In SOA the application consists of a collection of services that interact with one another through a separate communication layer. This separation of the application into smaller pieces that interact through a communication layer is often referred to as ‘loose-coupling’ which is meant to engender lower overhead of coordination (this is only achieved though if services do not rely on each other synchronously, in which case one service failure will have a larger ripple impact on the end user experience). Although there are differences between SOA and microservices, they are not strictly or consistently defined. Common differences that are often referred to include:
- Scope & Size: microservices are often smaller as the name implies so the service would perform one specific task like adding an item to a shopping cart whereas a service in an SOA design may contain all of the functionality for something like cart checkout
- Service to Service communication: when SOA architecture first emerged, normally services communicated through a separate system called an Enterprise Service Bus. Whereas in a microservices context, it is more common for services to communicate through a cloud friendly asynchronous event streaming platform (e.g., Kafka, originally created at LinkedIn)
- Storage: it was more common in early SOA architectures that the services all share one database. In a microservices architecture, it is much more common (and is a best practice) to have one datastore per service.
These differences – again – are not strictly defined as part of these architectural concepts and patterns. So you can think of microservices as just as an evolution of SOA, that to a large extent grew out of the ever-evolving building blocks that are available to build applications (e.g. Kafka for real time communication, containerization and many public cloud innovations etc.)
AKF defines microservices as an architectural approach that emphasizes team autonomy, ownership and comparatively small development and deployment size to improve software agility, scalability, complexity, velocity, and time to market. Individual microservices split an application into smaller pieces of functionality that are aligned to business domain or problem. For example, in an e-commerce application there may be one or many microservices associated with checkout.
The approach decomposes or disintegrates an application into multiple services. Each microservice (or micro-service) should have the following attributes:
- independently deployed (or capable of independent deployment)
- independently executed (not dependent on another service for to run)
- “owns” (or is responsible for creating) some unique business capability and its associated outcomes (e.g. checkout or a part of the checkout process)
- owned by a single team (no two teams own a microservice)
- “owns” its own data store or persistence - and ideally the only solution accessing that store (one database per service)
Microservices done well help teams scale but it’s very important to consider that implementing a more distributed architecture with separate services adds a different type of complexity than having one large monolithic code base that typically gets hard to understands as it grows over time. You may hear the terms “distributed monolith” or “spaghetti microservices” and both are pejorative phrases for unstructured and difficult to maintain source code.
Why are microservices important?
Microservices are important because they enable small teams (a team of less than 15 – or that which can be fed with 2 pizzas) to operate autonomously and therefore optimize for SPEED to market.
Referring back to Jeff Bezos manifesto to Amazon in 2002, he declared that ALL communication between individual services that a team built must be through application programming interfaces (API’s). This declaration was trying to define a simple but critical principle to rule all principles, with the objective of ensuring all teams can iterate rapidly to build new product capabilities at a massive organizational scale.
When well-constructed for the business need (size, growth etc.), microservices result in the following benefits:
- faster deployments and faster time to market for any capability resulting in lower costs and increased revenue
- higher team agility through lower inter-team dependence
- lower change risk (smaller scope of change)
- higher team accountability and empowerment to achieve business outcomes
- independent service scalability and independent cost of scale per service
- better and more reliable availability
- flexibility to apply the best tools to any outcome (programming language, technology, etc.)
- higher team morale when teams are constructed cross functionally and with appropriate empowerment
Key points for CEOs and Board members
- More microservices are NOT always better. When microservices were first popularized, ‘purists’ would often scope them to be as small as possible meaning the service performed only one task. Instead, they should be sized based on the business outcome considerations, ideally with one team owning one service. When microservices are sized at the lowest level of granularity possible, it often adds unnecessary complexity that results in “spaghetti microservices” which can result in lower quality and availability.
- A monolith is often best for startups! Microservices may not be appropriate in the initial stages of company growth when the focus is on product/market fit exploration and the customer base is small. In the early phases of growth, a well-constructed {link again to Berardi’s post} monolith that lays the foundation to make future decomposition more straightforward is often a better choice.
- Beware of antipatterns in service interactions. Normally multiple services will be needed to complete a customer interaction. Microservices should interact with each other in an asynchronous fashion so that when one is unavailable, other services can continue to function and minimize customer impact. We define multiple patterns/anti-patterns to help guide this construction of a full user experience.
- Ideally microservices should align to business outcomes for customers such as browsing, checking out etc. Often there are generic capabilities like managing Identity that are also separate services but ideally, they map to a vertical slice of functionality based on what your product does.
- As a team splits services, they should maintain a common view of their product domains and refresh this view regularly, e.g. 1-2 times/year especially if the business is growing and evolving rapidly. Domains ideally map to product/customer outcomes and set the foundation for what services should exist. One service maps to one scrum team such that teams are aligned to desired architecture and architecture is aligned to customer/business outcomes.
- Teams should have a stated philosophy and/or decision criteria for when to split a service to guide and align across the organization. Following is a decision tree to help guide these decisions in a common way.
- Microservices address only ONE (albeit an important one) dimension of good application architecture. To simplify the framework for addressing scaling of an application AKF has created a scale cube that covers other major dimensions, microservices align to the Y axis of the Scale Cube.
Common CEO questions about Microservices
How do I determine how many microservices are right for my team?
Ideally one scrum team (~8-12 people) owns one service. Of course, since a growing business is always evolving, ongoing refreshes of the Products’ domains help to guide this decisioning of when to split services. Avoid sharing a service across two teams as each team should be independent and not have to wait on others to complete their work whenever possible. Such sharing eliminates one of the greatest benefits of micro services – specifically engendering team ownership and reducing coordination for the purposes of faster throughput/velocity per team.
What are the right questions to be asking my team about this?
The previous section regarding key points for CEOs includes useful questions to ask the engineering team regarding how and when they decide to split services, as well as how services interact with each other and how many services on average does each 2-pizza scrum team own.
Your team should have a set of simple rules for knowing to split a service vs keep it as-is. We have a decision tree to help guide engineering teams.
If my code base is a monolith now – when should I move to microservices?
As an engineering team grows, you should monitor how time to market changes, especially for smaller to medium sized changes. Associated variables to consider in assessing this include:
- Engineering velocity is decreasing – which is the relative quantification of the amount of work in a sprint
- Cost per unit of value creation is increasing based on meaningful product success outcomes such as revenue, usage etc.
- Cross coordination level required between teams to make changes is increasing
- Production quality is worsening – lower quality potentially indicates rising complexity
If the time to market trend slows, the above metrics are all strong indicators that it is time to decompose the application into smaller independent pieces.
How do I know if I have “spaghetti microservices?”
As with the previous question, indicators of poorly constructed or orchestrated microservices include deterioration in quality and/or time to market, customer impacting incidents taking a longer time to resolve and/or one service often resulting in a catastrophic broader failure in customer facing functionality.
What Microservices are not
- Microservices are only one aspect of a healthy application. They are a foundational part of good architecture though, and if not done well, there will be business impacts in slower time to market and downtime/customer quality.
- Microservices do not address cross-cutting concerns of which there are many to consider to be successful, e.g. application logging/monitoring, deployment automation, secure coding practices and the list goes on.
- Microservices do not fix ‘bad code’ and service interaction antipatterns. Ideally the team is using automated (application scanning for best practices) and manual (code reviews) to keep the code healthy in all respects.