GraphQL Federation is a powerful technique for building a unified GraphQL API across multiple microservices, allowing them to work seamlessly together as a single data graph. Express.js, as a flexible web server framework, is well-suited for setting up and managing GraphQL federated services.
GraphQL Federation allows developers to build multiple independent GraphQL services and then combine them into a single unified graph. Instead of managing a large, monolithic GraphQL schema, you can create schemas specific to each microservice and then stitch them together to form one API. This approach is especially helpful when managing complex applications where different teams are responsible for different domains or services.
Integrating GraphQL Federation in a microservice architecture offers several advantages:
GraphQL Federation uses several components to unify schemas across services:
User
, Product
).To implement GraphQL Federation with Express.js, you’ll need to set up the server, configure federated services, and use the Apollo Federation library.
You’ll need express
, apollo-server-express
, and @apollo/gateway
to set up the GraphQL server and gateway.
npm install express apollo-server-express @apollo/gateway graphql
Initialize an Express.js server that will host the federated GraphQL API.
// server.js
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const { ApolloGateway } = require('@apollo/gateway');
async function startServer() {
const app = express();
// Initialize the Apollo Gateway
const gateway = new ApolloGateway({
serviceList: [
{ name: 'users', url: 'http://localhost:4001/graphql' },
{ name: 'products', url: 'http://localhost:4002/graphql' },
],
});
const server = new ApolloServer({
gateway,
subscriptions: false,
introspection: true,
playground: true,
});
await server.start();
server.applyMiddleware({ app, path: '/graphql' });
app.listen({ port: 4000 }, () => {
console.log(`🚀 Gateway ready at http://localhost:4000/graphql`);
});
}
startServer();
Each microservice needs to have its own GraphQL schema and should be set up to support federation.
The User
service will handle user-related queries and expose an entity for federation.
npm install express apollo-server-express @apollo/federation graphql
// user-service.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const { buildFederatedSchema } = require('@apollo/federation');
const typeDefs = gql`
extend type Query {
getUser(id: ID!): User
}
type User @key(fields: "id") {
id: ID!
name: String
email: String
}
`;
const resolvers = {
Query: {
getUser: (_, { id }) => ({ id, name: "Alice", email: "alice@example.com" }),
},
User: {
__resolveReference(user) {
return { id: user.id, name: "Alice", email: "alice@example.com" };
},
},
};
const app = express();
const server = new ApolloServer({
schema: buildFederatedSchema([{ typeDefs, resolvers }]),
});
server.applyMiddleware({ app, path: '/graphql' });
app.listen({ port: 4001 }, () => {
console.log(`User service running at http://localhost:4001/graphql`);
});
http://localhost:4001/graphql
and query:
query {
getUser(id: "1") {
id
name
email
}
}
The Product
service will handle product-related queries and connect to the User
entity.
// product-service.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const { buildFederatedSchema } = require('@apollo/federation');
const typeDefs = gql`
extend type Query {
getProduct(id: ID!): Product
}
type Product @key(fields: "id") {
id: ID!
name: String
owner: User
}
extend type User @key(fields: "id") {
id: ID! @external
}
`;
const resolvers = {
Query: {
getProduct: (_, { id }) => ({ id, name: "Laptop", owner: { id: "1" } }),
},
};
const app = express();
const server = new ApolloServer({
schema: buildFederatedSchema([{ typeDefs, resolvers }]),
});
server.applyMiddleware({ app, path: '/graphql' });
app.listen({ port: 4002 }, () => {
console.log(`Product service running at http://localhost:4002/graphql`);
});
http://localhost:4002/graphql
and query
query {
getProduct(id: "101") {
id
name
owner {
id
}
}
}
In a federated setup, services can reference each other by defining shared entities. For example, the Product
service references the User
entity by using an @key
directive and @external
fields.
GraphQL Federation with Express.js enables the creation of highly modular and scalable architectures. By splitting services based on domains and connecting them through a federated gateway, teams can develop and deploy independently. Happy Coding!❤️