Microservices Design and Best Practices
Some of my notes and best practices learned over the years designing and developing microservices.
UI
- Thin layer. Do not add any business logic to this layer.
- Contains React code and may contain web assets.
- Has a shared look and feel that provides a visual consistency to the project.
- It is a web application, like Play, to allow us to set and remove cookies and delegate calls to the proxy.
- It can be simpler to share data among react components.
- It does not handle sessions so it can be part of a distributed system.
- May be part of a larger web application, like a portal.
- CSS can be shared across the application, achieving consistency in a simpler way.
- It is stateless.
- It is deployed independently of other components and services.
- It can be configured locally along with a proxy to set up fake requests during development. This way front-end developers do not have to wait for back-end developers to complete their work.
The following are some issues that may come up when we split the UI in multiple subprojects:
- Subprojects don’t share a common look and feel
- It is difficult to share state among React components
- Dependecies issues may come up if we have different component versions across the subprojects
So for those reasons it’s preferred to have a single UI project.
Proxy
- Forwards calls to business services.
- Calls Auth and has logic to allow or deny calls to other services based on Auth result.
- Does not perform any business logic. For example, it does not know how to join orders and products.
- Performs caching operations.
- It is statless.
- Can be deployed on its own.
- Never calls external services.
- Can be implemented with AWS’ API Gateway.
Auth
- Performs user authentication.
- Performs user authorization.
- Manages and caches sessions.
- Creates and validates JWTs.
- It is deployed on its own.
- May use external Auth services like Facebook.
- May return a list of privileges that can be easily matched by the proxy to determine whether it can forward a request to a specific business microservice or not.
- Or may return 200-OK/403-Forbidden in response to a request containing a target business service and operation.
- May return a JWT with minimum user data and session data to be passed by the Proxy to other business microservices.
Business
- Domain oriented. We can use a hexagonal architecture.
- Services can call other services and perform business logic.
- There may be an optional orchestrator in charge of handling complex business logic.
- Services always return full responses. The proxy should never have to deal with calling multiple microservices to complete a request. For example, if a request requires an order that includes a list of items, the orders microservice should make any additional requests to other services to complete it.
- They have their own database and should never interact with the database of any other service.
- They are stateless.
- They return caching headers that allow the Proxy to decide whether resources should be cached and for how long.
- They can be deployed independently of other services.
- They may use kafka (or a similar technology) for asynchronous calls.
- They should not be publicly accessible.
- If you have to make multiple calls to another business microservice, consider adding a new endpoint to it to handle this type of requests. This approach is helpful as well for those scenarios that may be surrounded by a transaction. For example, a two operation process like money transfer between accounts should not be implemented by calling the withdraw and deposit endpoints on the same microservice, but rather by using a single transfer endpoint that internally performs both operations.
- It is usually until you have to make changes when you realize whether your microservices granularity is correct. If you find that a change requires updates to several business microservices, then maybe your services are too fine grained. On the other hand, if testing becomes too long compared to the coding effort, then maybe the microservices are too coarse grained.
References
- Kuc, Karol. Hexagonal Architecture by example - a hands-on introduction. Allegro Tech. https://blog.allegro.tech/2020/05/hexagonal-architecture-by-example.html
- robloxro. Summary of the Domain Driven Design concepts. Medium. https://medium.com/@ruxijitianu/summary-of-the-domain-driven-design-concepts-9dd1a6f90091
- Brown, Kyle. What’s the right size for a microservice? Medium. https://kylegenebrown.medium.com/whats-the-right-size-for-a-microservice-bf1740370d47
- Gupta, Lokesh. How to design a REST API. REST API Tutorial. https://restfulapi.net/rest-api-design-tutorial-with-example/
- Client Error Responses. MDN Mozilla Developers Network. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses