API Namespacing Pattern for GraphQL API Gateways
API Namespacing is a pattern for GraphQL API Gateways that allows you to merge incompatible GraphQL APIs into a single unified GraphQL Schema.
Problem
When using the API Aggregation / Composition Pattern, your goal is to combine multiple heterogenous APIs into a unified GraphQL Schema. However, as these APIs were developed independently and without coordination, they may have conflicting names for types and fields.
For example, if you have two APIs, one for a blog and one for a forum, they
may both have a Post
type. If you try to combine these two APIs into a single schema,
it will be ambiguous which Post
type you are referring to.
After all, how would you know if Post
refers to a blog post or a forum post?
And if we merged the two types somehow,
how would you know which fields are available on the merged type?
We could manually rename the types and fields to avoid these conflicts, but this might be tedious and error-prone. In addition, we may not have control over the APIs we are aggregating, so this may not even be an option.
Solution
The solution to this problem is to use the API Namespacing Pattern. The easiest way to implement this pattern is by prefixing all type definitions, directives and root fields names with a namespace.
Root field names need to be prefixed because all root fields, that is, fields on the Query, Mutation and Subscription types, will be merged, and we need to avoid conflicts between them as well.
In addition to just prefixing names before we merge the schemas, we need to store information about the original names of types and fields. This is because we need to be able to "rewrite" all names before we're sending an Operation to the origin API.
Example
Let's say we have two APIs, one for a blog and one for a forum.
The blog API has a Post
type with a title
field,
and the forum API has a Post
type with a content
field.
# Blog API
type Post {
title: String!
}
type Query {
posts: [Post!]!
}
# Forum API
type Post {
content: String!
}
type Query {
posts: [Post!]!
}
We can use the API Namespacing Pattern to combine these two APIs into a single schema.
First, we need to add a namespace to all type definitions, directives and root fields names.
We'll use the namespace blog_
for the blog API and forum_
for the forum API.
# Blog API
type blog_Post {
title: String!
}
type Query {
blog_posts: [blog_Post!]!
}
# Forum API
type forum_Post {
content: String!
}
type Query {
forum_posts: [forum_Post!]!
}
Now we can merge these two APIs into a single schema.
type Query {
blog_posts: [blog_Post!]!
forum_posts: [forum_Post!]!
}
type blog_Post {
title: String!
}
type forum_Post {
content: String!
}
What's great about this pattern is that we can now query both APIs from the same schema,
and our IDE will assist us with auto-completion in finding the right fields.
If we want to query the Blog
API, we start typing blog
and our IDE will suggest the blog_posts
field.