Lenny’s Little Apollo Book

Apollo Federation Patterns: Polymorphic Relationships

April 28, 2020

This post is part of a series about Apollo Federation architectural patterns. Check out the introduction for some background on how the example code is structured.

By storing type names as well as IDs, you can model polymorphic relationships that cross any number of services.

This post comes with a caveat: introducing interfaces and unions into your federated schema can dramatically complicate things. Be sure that your domain truly requires them before going down this route!

In this example, we allow comments to be associated with Posts and Photos. The comments service defines a Commentable interface that both Posts and Photos conform to. Note that inline fragments like ... on Post are necessary for the query planner to know how to fetch data like Post.content or Photo.url from the other graph services.

CodeSandbox Demo

The Query Plan

Notice how the requests to the posts and photos services are performed in parallel.

If you drop the ... on Photo fragment, the query planner also drops the request to the photos service. The query planner relies on the concrete types specified in fragments to know which services it needs to fan out to.

QueryPlan {
Sequence {
Fetch(service: "/sandbox/src/services/comments.js") {
{
comment(id: "c1") {
id
text
on {
__typename
id
... on Post {
__typename
id
}
... on Photo {
__typename
id
}
}
}
}
},
Parallel {
Flatten(path: "comment.on") {
Fetch(service: "/sandbox/src/services/posts.js") {
{
... on Post {
__typename
id
}
} =>
{
... on Post {
title
content
}
}
},
},
Flatten(path: "comment.on") {
Fetch(service: "/sandbox/src/services/photos.js") {
{
... on Photo {
__typename
id
}
} =>
{
... on Photo {
title
url
}
}
},
},
},
},
}

Written by Lenny Burdette in San Francisco. You can follow him on twitter but he doesn't tweet. Opinions written here do not necessarily reflect those of his employers and are subject to change.