Key Takeaways
- A GraphQL gateway merges the advantages of a traditional API gateway with GraphQL, enabling software engineers to fetch data from multiple sources while maintaining frontend efficiency.
- The Backend-for-frontend (BFF) architecture pattern reduces the number of requests from the frontend, simplifying the process by allowing a single request to the API gateway, which then fetches data from each backend service and combines it.
- GraphQL offers several strengths for a BFF, including efficient data fetching, a single endpoint for all requests, and flexible queries that allow frontends to select only the data they need for each request.
- Three recommended frameworks for building a GraphQL gateway include Hasura, StepZen, and Graphweaver. These frameworks offer features such as multiple source connections, routing, batching, security, cross-datasource filtering, and extensibility.
In this article, we’ll discuss the problem of how to fetch data from multiple sources while still keeping our frontend snappy, and a potential solution: using a GraphQL Gateway.
As software engineers, we’ve all faced the challenge of combining data from many systems. Even a single page requires data from several services to render.
Data is everywhere, from CRMs to financial systems and SaaS platforms to databases. Every business inevitably buys a plethora of SaaS platforms, then wants a unified business view on top of all of them. We have to embrace this head on and integrate everything.
A GraphQL gateway combines the benefits of a traditional API gateway with GraphQL.
We’ll start by discussing the benefits of an API gateway, and then look at how GraphQL fits in. Stick around to the end of the article, where we look at some frameworks for building our own API gateway.
Benefits of an API Gateway
Securing our public-facing APIs against hackers is a full-time job. Over time, organizations have evolved to create many APIs, from SOA to microservices. Instead of putting these APIs directly onto the Internet, organizations prefer to add an extra layer of security that sits in front of all these APIs and ensures that access to data always follows the same authentication rules.
They do this with an API gateway.
Products such as Kong or Apigee expose internal APIs from a central location. They act as a reverse proxy with features like API key management, rate limiting, and monitoring.
The API gateway allows us to control who and what has access to each service, monitoring the connections and logging access.
More recently, apps have been required to combine data from an API gateway and other external SaaS providers. This means that the old centralized tool — which ensured our rules were followed — is now bypassed on a regular basis.
Imagine we’re building a web app for our company. We have a task to create the user profile page. During the login process, we need to combine data from many systems:
- Salesforce CRM: holds the general customer data such as first and last name.
- Orders: recent orders are in an ordering system within the organization.
- Notifications Service: the notification settings and recent messages are in an app-specific database connected to a Node.js service.
The client would need to make three separate requests to get the data, as represented in the image below.
In the image above, the web client sends three separate API requests and then has to combine the results in frontend code. Sending multiple requests affects the app’s performance, and combining this data increases the complexity of the code. In addition, if there’s more than one app, now all apps have to be aware of all backends, and a single API change in one service can result in updates to all of our applications.
We can do better. Ideally, we want to reduce the requests from three to a single fetch. We could create a new service to do that — a service that orchestrates requests to backend services. This idea has a name: the BFF pattern.
The Backend-for-frontend (BFF) architecture pattern allows a single request from the frontend.
But how does it work? Let’s look at this pattern in more detail.
The Benefits of the BFF Pattern
With the BFF pattern, an application sends a single request to the API gateway. The BFF service then requests data from each backend service and combines it. Finally, the data is filtered, returning only the data needed for the front end, reducing the data sent over the wire.
As illustrated in the image above, we’ve introduced an extra layer into the stack to orchestrate the request.
The user profile endpoint returns the data needed for that app on the profile page. Reducing our three requests to a single request has fixed our previous performance issue.
But we aren’t finished yet.
The business has decided to release a mobile app. The mobile app also has a profile page, but this screen displays much less profile information.
At this point, the mobile team has two options. The team could reuse the web team’s endpoint, which would mean we over-fetch the data (fetching more data than is needed for the mobile app). The alternative is that the mobile team creates their own BFF.
Not surprisingly, the mobile team decide to create their own BFF, as they want good performance for their app.
As illustrated in the image above, things are starting to get complicated, and we now have two new issues:
- Each team has to create a new BFF service for each application they create, slowing each team down and making it hard to standardize.
- Each BFF needs to be pen-tested to ensure it’s secure.
How do we solve these issues?
We need a solution where each app can select the data it needs, and it should be a single API used by all applications in the company.
As BFFs have matured, many developers have started experimenting with GraphQL instead of REST.
Let’s look at how this technology can help.
The Benefits of GraphQL for a BFF
GraphQL has many strengths that make it an ideal technology for a BFF:
- Efficient Data Fetching. GraphQL enables clients to request exactly the data they need and nothing more. This improves performance by reducing the data that’s transferred from the API.
- Single Endpoint. Instead of exposing many endpoints via the gateway, GraphQL uses a single endpoint for all requests. This simplifies the maintenance and the need to version.
- Flexible queries. Clients can construct queries by combining fields and relationships into a single request. This empowers frontend developers to optimize data fetching, increasing performance. In addition, if the requirements for the frontend change, it can be updated to fetch different data without altering the backend in any way.
Frontends can now select only the data they need for each request.
We can now connect both our apps to the same GraphQL server, reducing the need for a second BFF service.
We can now share the BFF for any app in the organization. We also have a single endpoint that needs to be pen-tested.
But again, we’ve introduced a new problem! We still have to manage two systems — the API gateway and the GraphQL BFF.
What if we combined the two into a GraphQL gateway?
Next, let’s look at how a GraphQL gateway works.
What is a GraphQL Gateway?
A GraphQL gateway combines an API gateway with a GraphQL API to get the best of both technologies.
Let’s recap the benefits:
- Developers have a single API endpoint to request data from. This reduces over- or under-fetching, as each application selects only the data it needs.
- The GraphQL gateway is shared by many apps within the organization. This means we have reduced our security exposure to a single API endpoint.
- We only have a single service to manage, now that the BFF is combined with the gateway.
The diagram below shows how the user profile API request works with a GraphQL gateway.
In the image above, the client sends a single request to the GraphQL gateway, requesting the data it needs. The gateway makes individual requests to each service and combines the results. We now only have a single service to manage and deploy.
Hopefully, you’re ready to try this for yourself. Next, let’s look at how we can build a GraphQL gateway.
Building a GraphQL Gateway
When choosing a gateway framework, we want to look for some key features:
- Multiple Sources. The gateway must connect to many data sources — from databases to SaaS — and we should be able to create our connections.
- Routing. The gateway should be able to request data from the underlying services directly.
- Batching. Multiple queries to the same service are sent in a batch, reducing the number of requests.
- Security. Authentication and authorization should control who can access the connected data.
- Cross Datasource Filtering. Powerful filters should be available to not over-fetch the data needed by the client.
- Extensible. Developers should be able to extend the code with middleware or functions to fit their needs.
There are many frameworks to choose from, but here are the top three that I recommend exploring further.
Hasura
Hasura has gained popularity over the years, initially as a GraphQL-over-Postgres server. However, it has added the ability to connect to external systems.
We can connect a “Remote Schema”, which combines GraphQL from other servers.
There are some downsides to this approach. The first is that we need to create and manage our remote schema in a separate service, and this service must be a GraphQL endpoint. This leads to the second issue: we can’t connect the data source directly.
In addition, Hasura doesn’t allow us to filter data in one data source based on the values in another. This might sound academic, but it’s actually pretty common that we want to express something like, “Give me orders where the customer name is ‘ABC’.”
This offers flexibility, but at the expense of running multiple services. Let’s look at an option that will connect directly.
StepZen
StepZen allows us to connect to the data source directly from the GraphQL server. This reduces the need to run multiple services to create a gateway.
To connect Stepzen to a data source, we create a GraphQL schema file like this:
type Query {
anything(message: String): JSON
@rest (
endpoint: "https://httpbin.org/anything"
method: POST
headers: [
{name: "User-Agent", value: "StepZen"}
{name: "X-Api-Key", value: "12345"}
]
postbody: """
{
"user": {
"id": "1000",
"name": "The User"
}
}
"""
)
}
In this example, we’re connecting the server to a database using the custom schema.
There’s another option that you may prefer, and that is a code-only approach. Let’s look at that next.
Graphweaver
For the past few years, I’ve been working on an open-source product called Graphweaver, which can be used as a GraphQL gateway.
It connects directly to our data sources and creates an instant GraphQL API. This API includes all the CRUD operations we might expect to create, read, update, and delete. It auto-generates filters, sorting, and pagination arguments, saving time. We can extend the built-in operations with our code for complete flexibility.
Graphweaver has out-of-the-box data connectors for databases such as Postgres and Mysql and SaaS providers like Xero and Contentful.
Making changes or connecting data sources involves writing Typescript code, giving us complete customization.
If you’re interested in creating your own GraphQL API, I highly recommend you take a look at the Graphweaver GitHub code.
Conclusion
In this article, we’ve looked at how to replace our current API gateway and BFF pattern with a single GraphQL gateway.
We’ve looked at the benefits of an API gateway and why organizations use them. Version control, rate limiting and access management are some of the reasons.
We also looked at the BFF pattern and how it orchestrates API requests for frontend apps.
Finally, we looked at GraphQL and how this is a beneficial technology for BFFs.
Ultimately, this led us to creating a GraphQL gateway, and we looked at three options for creating our own: Hasura, StepZen, and the product I’ve been working on, Graphweaver.
I hope this article has convinced you to try a GraphQL gateway of your own, and if so, that you’ll consider giving Graphweaver a try.
Frequently Asked Questions (FAQs) on GraphQL Gateway
What is the main purpose of a GraphQL Gateway?
A GraphQL Gateway serves as a single point of entry for all your GraphQL operations. It is responsible for routing requests to the appropriate services, aggregating the responses, and sending them back to the client. This allows you to manage multiple GraphQL schemas and services from a single location, making your application more scalable and easier to maintain.
How does GraphQL Gateway differ from traditional API gateways?
Traditional API gateways are designed to handle RESTful APIs, which operate on a different paradigm than GraphQL. GraphQL Gateway, on the other hand, is specifically designed to handle GraphQL operations. It provides features like schema stitching and merging, which allow you to combine multiple GraphQL schemas into a single one. This is something that traditional API gateways cannot do.
What is schema stitching in GraphQL Gateway?
Schema stitching is a feature of GraphQL Gateway that allows you to combine multiple GraphQL schemas into a single one. This is particularly useful when you have multiple services, each with its own schema, and you want to expose them as a single API. Schema stitching takes care of merging the schemas and resolving any conflicts, providing a seamless experience for the client.
How does GraphQL Gateway improve performance?
GraphQL Gateway can significantly improve performance by reducing the number of round trips between the client and server. Instead of making multiple requests to different services, the client can make a single request to the GraphQL Gateway, which then routes the request to the appropriate services, aggregates the responses, and sends them back to the client. This reduces network latency and improves overall performance.
Can I use GraphQL Gateway with microservices?
Yes, GraphQL Gateway is particularly well-suited for microservices architectures. Each microservice can have its own GraphQL schema, and the Gateway can stitch these schemas together to provide a unified API. This allows you to manage and scale your microservices independently, while still providing a consistent interface to your clients.
Is GraphQL Gateway compatible with all programming languages?
GraphQL Gateway is language-agnostic, meaning it can be used with any programming language that supports GraphQL. This includes popular languages like JavaScript, Python, Ruby, and Java, among others.
How does GraphQL Gateway handle errors?
GraphQL Gateway provides robust error handling capabilities. If an error occurs in one of the services, the Gateway will return a detailed error message to the client, including information about which service caused the error and what went wrong. This makes it easier to diagnose and fix issues.
Can I use GraphQL Gateway with serverless architectures?
Yes, GraphQL Gateway is compatible with serverless architectures. You can deploy your Gateway as a serverless function, which allows you to take advantage of the scalability and cost-efficiency of serverless computing.
How does GraphQL Gateway handle security?
GraphQL Gateway provides several security features, including authentication and authorization, rate limiting, and request validation. These features help protect your services from unauthorized access and abuse.
Can I use GraphQL Gateway with existing RESTful APIs?
Yes, you can use GraphQL Gateway with existing RESTful APIs. The Gateway can wrap your RESTful APIs in a GraphQL schema, allowing you to take advantage of the benefits of GraphQL while still using your existing APIs.
Steve Keep has worked in Tech for over two decades, mostly as a software engineer. He’s a web enthusiast who finds time to create sites using the latest technology. He's been lucky enough to have worked with it all — from IoT, mobile and AI. He's currently working on Graphweaver, which turns multiple data sources into a GraphQL API.