Apollo Federation
Apollo Federation is a specification that applies microservice architecture through GraphQL APIs.
Thanks to Envelop’s Apollo Federation plugin, we can use GraphQL Yoga to build our gateway server.
💡
As documented in the Apollo Federation
docs ,
@apollo/gateway
package doesn’t support GraphQL v16 so you have to install
graphql@15
.
💡
Please note that Apollo Federation implementation doesn’t support GraphQL Subscriptions. If you need to use Subscriptions with a Federated Gateway you can use Schema Stitching .
Gateway
Installation for Gateway
Example Gateway
import { createServer } from '@graphql-yoga/node'
import { ApolloGateway, RemoteGraphQLDataSource } from '@apollo/gateway'
import { useApolloFederation } from '@envelop/apollo-federation'
/**
* Needed since federation remote data source fetcher
* doesn't support `application/graphql-response+json` content type
* https://github.com/apollographql/federation/issues/2161
* And yoga defaults to `application/graphql-response+json` as per the spec.
*/
class DataSource extends RemoteGraphQLDataSource {
willSendRequest({ request }) {
request.http.headers.set('accept', 'application/json')
}
}
// Initialize the gateway
const gateway = new ApolloGateway({
serviceList: [
{ name: 'accounts', url: 'http://localhost:4001' },
{ name: 'products', url: 'http://localhost:4002' }
// ...additional subgraphs...
],
introspectionHeaders: {
accept: 'application/json'
},
buildService({ url }) {
return new DataSource({ url })
}
})
// Make sure all services are loaded
await gateway.load()
const server = createServer({
plugins: [useApolloFederation({ gateway })]
})
// Start the server and explore http://localhost:4000/graphql
server.start()
Federation Service
You don’t need any extra plugins for Yoga for Federation Service.
Installation
Example User Service
const { parse } = require('graphql')
const { buildSubgraphSchema } = require('@apollo/subgraph')
const { createServer } = require('@graphql-yoga/node')
const typeDefs = parse(/* GraphQL */ `
type Query {
me: User
}
type User @key(fields: "id") {
id: ID!
username: String
}
`)
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' }
}
},
User: {
__resolveReference(user, { fetchUserById }) {
return fetchUserById(user.id)
}
}
}
const server = createServer({
schema: buildSubgraphSchema([{ typeDefs, resolvers }]),
port: 4001
})
server.start().then(() => {
console.log(`🚀 Server ready at http://localhost:4001`)
})
Working Example
Check our working example to try it out.