When your organization starts to grow, many (independent) services with its features are created and consumed. Therefore, clients (front-end) need to call multiple services, this becomes quickly a nightmare to manage and deal with different versions and endpoints of those services. Additional problems like too many round trips, security issues and cross-cutting concerns like authentication and SSL are also lurking around. A possible solution is to introduce an API gateway which provides a single endpoint and deals with security, service management and aggregating requests to underlying services.
However many traditional API gateways are hard to configure, not development friendly and are hard to understand. Additionally, they provide too much out of the box which eventually will leak business logic into the gateway layer.
In my opinion, a gateway should have the following responsibilities:
Documentation of all possible routes
Schema(s) management
Being close to the internal services
Limited authentication
Rate limiting
Stitching different internal sources (more on this later)
Caching
Logging
Tracing
With these requirements, we now will look at why GraphQL is a great fit when used in a certain way.
GraphQL as an API gateway
GraphQL gives frontend developers the ability to fetch exactly the data they need without over-/under fetching data. Additionally, it provides a strongly typed schema which opens a possibility for great frontend tooling and having great API documentation out of the box. Because of this, versioning the schema is done differently. With tools such as graphql-hive we can monitor the gateway schema and set up alerting when a breaking change is introduced into the gateway. Additionally, you can have a full history of schema changes.
Tools like Hasura, Wundergraph and Graphql-Mesh provide the ability to stitch underlying services to provide a unified graph. Additionally, all of those tools provide the ability to do rate-limiting, authentication and caching.
However, exposing graphQL to the internet introduces several security challenges which should take into consideration. See my previous blog post for more information: https://ilijanl.hashnode.dev/how-to-secure-and-make-graphql-blazingly-fast
Create a GraphQL API gateway with Hasura
Using Hasura and edge functions we can create a high-performance and secure API gateway with the following features:
Remote joins: join data across different services
CDN caching: using Vercel's edge functions
Schema configuration: using Hasura console and metadata
Authentication: using Hasura's authentication system
Rate limiting: inside edge functions
Additional features such as logging, tracing and schema versioning can be handled by graphql-hive, but the setup falls outside this article.
I have created a starter template which has the following architecture:
It is important to note that the Hasura API gateway should not be directly accessible by the clients in production. Therefore a simple BFF (backend for frontend) in a form of an edge function is used to whitelist all the operations used by the frontend and send an additional gateway secret to the Hasura API Gateway. For a better understanding see my previous article: https://ilijanl.hashnode.dev/how-to-secure-and-make-graphql-blazingly-fast.
More information about using Hasura as an API gateway can be found here: https://hasura.io/docs/latest/resources/use-case/api-gateway/
The front end, which is built with NextJS, is using GraphQL codegen to have type-safe queries and mutations against the gateway, thus providing a great DX for frontend developers.
Additional services can be added by using Hasura's remote schemas https://hasura.io/docs/latest/remote-schemas/overview/ or actions https://hasura.io/docs/latest/actions/overview/
The gateway should be hosted close to the services and databases which are used by the gateway to reduce roundtrip latency.
Conclusion
Using GraphQL as an API gateway opens a lot of possibilities for different tooling and better development experiences. However, exposing GraphQL directly to the internet potentially introduces a new set of security issues when not taken care of.
Thanks for reading.