Apollo Federation support in Graphene
My name is Igor Kasianov and I’m a lead on the backend team @Preply. In this article, I’ll share our experience connecting Python-based GQL graphs in Federated Graph with @apollo/gateway
Background
Preply’s backend was originally built as a monolith application in Python, we’ve adopted GQL API since 2017. In late 2018, we decided to migrate to a microservices architecture.
During the migration, we faced a challenge: how could we keep one single GQL endpoint for frontend after we transitioned to independent graphs for each backend microservice?
GQL schema stitcher: our first try
At the time, Apollo had just released their GQL schema stitcher. It looked like a promising way to combine graphs.
As we played with it, we discovered that all stitching logic was located in the API gateway services. This meant that we would need to update the GQL stitcher service code every time we updated or added a service. Even if we only had 2 nodes, MessageNode and FileNode, the API gateway would become too big.
The API gateway code was bulky and ruined the most important benefits of a microservices architecture — clear code ownership and a loosely coupled codebase.
You can check whole stitcher code example here
Apollo Federation: a perfect solution?
When Apollo Federation was released, it looked like the perfect solution. There was only one problem: libraries for JS, Java, Ruby & .NET existed, but there was no library for Python. Graphene library, which we’re using for GQL implementation in Python, didn’t support Federation.
Undeterred, we decided to create our own implementation of Graphene-Federation integration. It was quite straightforward based on Apollo Federation specification
Our implementation supports most of Federation spec, except 1 decorator:@provides
You can install it via pip: pip install graphene-federation
See an example
With Apollo Federation, it’s easy to split a big monolithic graph into a set of small graphs.
Let’s assume we have a graph in the monolith, where root querymessage
can have multiple files
monolith.py:
Now we decided to move files in separate microservice
monolith.py
file_microservice.py
@key(fields='id')
Determines that FileNode can be referenced from other services.@extend(fields='id')
Marks FileNode as external. We can add more fields to it if needed.id=external(graphene.Int(required=True))
Marks id as an external field.build_schema
does all magic
it adds_service
and_entities
fields and resolvers in the schema
it has the same signature asgraphene.Schema
You can find more info in the Core concepts of Apollo Federation docs.
In Federation, the API gateway code looks very simple and doesn’t require any updates when we make changes to underlying microservices.
Could you use graphene-federation?
If you use a SOA with GQL and need to connect your python-backed graphs in one endpoint, feel free to use Federation with graphene-federation.
You can open issues or contribute to graphene-federation.
See another open source project from Preply here: database-anonymizer