This project is a monorepo containing a GraphQL API gateway with gRPC back-end microservices all written in Node.js. This project is mainly used for learning/trial purposes only.
When creating GraphQL APIs, one must understand what Graph Theory and Graph Data Modelling are. One must also think in graphs as per the GraphQL specification recommends. A diagram of the graph data model is shown below.
- Users can write both posts and comments therefore, a users are authors posts and comments.
- Posts are authored by users and comments can be linked/submitted for them.
- Comments are authored by users and are linked/submitted to posts.
The GraphQL API acts as a gateway/proxy for the different microservices it exposes. The resolvers of the GraphQL API make calls to the gRPC servers/microservices in the back-end through gRPC client implementations of the back-end services which are defined through Protocol Buffers that also serves as the data interchange format. The gRPC microservices then handles the request to connect to databases or any other service it needs to serve requests.
A diagram of the architecture is shown below.
This architecture implements the following Microservice Design Patterns:
- Microservice Architecture
- Subdomain Decomposition
- Externalized Configuration
- Remote Procedure Invocation
- API Gateway
- Database per Service
- CQRS - GraphQL implements CQRS by default through resolution of graphs
Some of the benefits of adopting a microservice architecture are:
Individual Deployment
Each app can be deployed separately without knowledge of the other application. Each service is reusable in the entire tech stack. Upgrades can also be done in isolation from other application/microservice. This makes hot fixes and quick roll backs possible.
Fault Isolation
When an error or fault occurs, one will immediately know where it came from and debugging can be done immediately.
Easier Testing and Debugging
Having a very small codebase per microservice makes doing tests easier and debugging quicker by orders of magnitude.
Granular Scaling
Scaling can also be done on a per microservice deployment. Each microservice application can scale separately of others if it is serving more load than the others.
Better Observability
Operations will have better observability on the application as a whole since monitoring and logging can be done with granularity as is not mixed with other parts of the application.
GraphQL acts as the API Layer for the architecture. It takes care of listening for user requests and proxying those requests to the appropriate back-end microservice. The framework used for GraphQL in this application is graphql-yoga.
gRPC was chosen as the framework to do the microservices. Protocol buffers was used as the data interchange format between the client (GraphQL API) and the server (gRPC microservices). The framework used for gRPC in this application is Mali
PostgreSQL is used as the database and Redis is used as the cache.
Deployment is done with containers in mind. A Docker Compose file along with Dockerfiles for each project are given to run the whole thing on any machine. For production, it's always recommended to use Kubernetes for these kinds of microservices architecture to deploy in production. Istio takes care of service discovery, distributed tracing and other observability requirements.