-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
120 additions
and
0 deletions.
There are no files selected for viewing
120 changes: 120 additions & 0 deletions
120
content/posts/microservice-architecture-api-maturity.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
--- | ||
title: 'Microservices 101: API Maturity level' | ||
date: 2024-11-16T15:25:11+02:00 | ||
draft: false | ||
tags: | ||
- software architecture | ||
- microservices | ||
- API | ||
- swagger | ||
- OpenAPI | ||
--- | ||
|
||
### Communication between Microservices | ||
|
||
In a microservices architecture, services need to communicate with each other frequently. This communication can be broadly categorized into two types: East-West and North-South. | ||
|
||
East-West traffic is the internal communication between microservices. North-South traffic is the communication between the services and external systems or clients. Effective communication is vital for a microservices app's performance. | ||
|
||
### East-West | ||
|
||
As said, East-West communication involves interactions within the microservices ecosystem. This internal communication often uses RESTful APIs. It's critical to implement consistent, available, and resilient APIs. They ensure that microservices can communicate and be reliable as the system evolves. | ||
|
||
### The Domain Evolution | ||
|
||
Using an API requires some work. You must distil the business knowledge and needs into a few objects. They should act as requests and responses. You're representing the domain model in the API layer. | ||
|
||
As the world evolves, the domain model evolves too. We should adopt a process to easily support changing requirements. This way, our team won't be slowed by the new API and its maintenance. Microservices should adapt to changes in the domain model. This often means evolving API schemas and changing their behaviour. It also means deprecating old versions and creating new ones. All this must ensure compatibility and minimal disruption to service consumers. | ||
|
||
## API Maturity process | ||
|
||
The API maturity process is the result of tools, processes, and best practices that a team can agree on and apply. The process can be more or less strict. It depends on the project stage and the maturity of the engineering culture. | ||
|
||
It is a four-level strength management process. It ranges from 0, with poor management, to a highly structured and robust API. | ||
|
||
As the system grows more sophisticated, so will the team. They will need to advance through the maturity levels to operate with ease. | ||
|
||
Let's dive to the levels to see how we can incrementally improve team API workflows. | ||
|
||
### Level Zero: Cowboy 🤠 | ||
|
||
At this stage, you have very primordial API management practices. Most communication is verbal or informal, like email threads or ad-hoc meetings. Inconsistent API contracts cause confusion and slow communication. | ||
|
||
APIs are fragile and prone to breaking. There's no agreement on data structures, endpoints, or documentation. | ||
|
||
Example with Alice and Bob | ||
|
||
Alice and Bob are working on both sides of the API. Alice is consuming it from a TS app, while Bob is exposing it from a backend service. | ||
|
||
The two teammates agreed on the API behaviour and models as follows. | ||
|
||
``` | ||
PATCH /users/me/settings | ||
{ | ||
"email": { | ||
"marketing": "ON", | ||
"subscription": "ON", | ||
"mentions": "OFF" | ||
} | ||
} | ||
{"status": "ok"} | ||
``` | ||
|
||
Once the logic is in the server and client, all knowledge of the data semantics, request/response validation, and edge cases is lost. The only place where the knowledge is, is the code. This isn't a problem. But, with only the code, recreating a clear picture of the service API layer can be time-consuming and error-prone. | ||
|
||
It is enough if another dev joins the team. Or, if another client needs to use the same API. Then, all the info must be grasped again from the code. | ||
|
||
### Level One: From chaos leaning to documentation 📜 | ||
|
||
The team, now aware of their needs, must create a shared source of truth for the API semantics. It's the right time for this. | ||
|
||
They start putting down in documentation all the API knowledge distilled from: | ||
|
||
- the code | ||
|
||
- the verbal and written past communications between API providers and the consumers | ||
|
||
The team's implicit knowledge: If you call this endpoint more than once, all subsequent calls will fail. | ||
|
||
It's a great step forward for the project; the team have a place where they can get the API documentation at any time. | ||
|
||
It will be easy to onboard new team members and make the consumers aware of the API offered by the team. | ||
|
||
But, this is not a free lunch. The docs must align with the code. For each new change, the devs need to find and update the relevant API docs. | ||
|
||
This can be error-prone, easy to forget and in general it's an additional development cost. | ||
|
||
### Level Two: The raise of contracts 🤝 | ||
|
||
At this stage, the team starts using strict API contracts. They will use standards like [Open API specifications](https://www.openapis.org/what-is-openapi) and [IDL](https://en.wikipedia.org/wiki/Interface_description_language). The API spec must be reviewed and approved via standard processes, like Pull Requests. | ||
|
||
Implementing a strict API contract is not free of overhead for brownfield projects. Adopting a formal API definition requires some work. The team must first define all the implemented endpoints to the chosen IDL. They can also choose to start adopting well-defined contract on new implementations. They will then fill in the old API definition over time. | ||
|
||
A contract-first approach to a new project can have some overhead too, but it has also some nice side effects: | ||
|
||
It unblocks API consumers on developing their logic. You can define the contract first and then iterate on both sides: the server and the consumer. | ||
|
||
It sets guardrails to consider the interface and API semantics before coding. It guides developers to use a top-down design mindset. Focusing on the API first it helps on implementing things with all the requirements in mind. | ||
|
||
A formal contract lets us lint the API's syntax and semantics. This can be useful for large organizations wanting a uniform API. | ||
|
||
### Level Three: The glory of API management 🏆 | ||
|
||
The team want to massively automate their API lifecycle. So, on top of the previous best practices (like a well-defined API contract, a review process, and linted API specs), they want to deeply integrate the tools into the software development lifecycle through automation. | ||
|
||
Many open-source tools, like [openapi-generator tech](https://openapi-generator.tech), can be easily integrated into CI pipelines like Jenkins or GitHub Actions. | ||
|
||
Server must always be aligned with the API specs. | ||
|
||
They leverage an automated tool to generate server requests, responses, and routing definitions. That practices reduce bugs caused by misalignment between the API definition and the actual server implementation by an order of magnitude. | ||
|
||
You can also generate client code. | ||
|
||
Automated tools can generate client code from the API specs. This reduces manual work for consumers. It allows the provider to offer an out-of-the-box SDK. | ||
|
||
#### Full Example | ||
|
||
<script src="https://gist.github.com/simodima/15de93a0e3fabec017070cfee8fac348.js"></script> | ||
|
||
Every API maturity level has benefits and challenges. Organizations must find a balance that fits their size, complexity, and goals in their microservices journey. |