GraphQL Federation and Schema Stitching in Express.js

GraphQL has revolutionized API design by providing a flexible query language. For large-scale systems where multiple services expose their GraphQL APIs, combining these schemas efficiently becomes crucial. This chapter delves into two advanced techniques: GraphQL Federation and Schema Stitching, both of which allow developers to create unified schemas in Express.js applications.

Introduction to GraphQL Federation and Schema Stitching

What is GraphQL Federation?

GraphQL Federation is an architecture introduced by Apollo Federation to enable multiple GraphQL services to work together as a single unified API. It breaks down monolithic schemas into smaller, manageable services.

What is Schema Stitching?

Schema Stitching is another method to combine multiple GraphQL schemas into one, allowing a single query endpoint for clients. Unlike Federation, Schema Stitching doesn’t require custom resolvers in sub-services but relies on combining schemas directly.

Comparing GraphQL Federation and Schema Stitching

FeatureGraphQL FederationSchema Stitching
ArchitectureService-orientedCentralized
DependenciesRequires Apollo Federation librariesUses tools like @graphql-tools/stitch
ResolversDefined in each serviceCentralized in the stitching service
Best Use CaseLarge microservices architecturesSmaller-scale or legacy schemas

Setting Up Express.js with GraphQL Federation

Installing Required Libraries

To implement GraphQL Federation, you’ll need Apollo Federation libraries:

				
					npm install apollo-server-express @apollo/subgraph graphql

				
			

Example: Creating a Subgraph

A subgraph represents an individual service exposing a GraphQL schema.

Code for users Subgraph

				
					const { ApolloServer } = require('apollo-server-express');
const { buildSubgraphSchema } = require('@apollo/subgraph');
const express = require('express');
const { gql } = require('graphql-tag');

const typeDefs = gql`
  type User {
    id: ID!
    name: String!
  }

  type Query {
    users: [User!]!
  }
`;

const resolvers = {
  Query: {
    users: () => [
      { id: '1', name: 'Alice' },
      { id: '2', name: 'Bob' },
    ],
  },
};

const app = express();
const server = new ApolloServer({
  schema: buildSubgraphSchema({ typeDefs, resolvers }),
});

server.start().then(() => {
  server.applyMiddleware({ app });
  app.listen(4001, () => console.log('Users service running on http://localhost:4001'));
});

				
			

Gateway Service

The Gateway combines multiple subgraphs.

Installing Gateway Dependencies

				
					npm install @apollo/gateway apollo-server-express graphql

				
			

Code for Gateway

				
					const { ApolloServer } = require('apollo-server-express');
const { ApolloGateway } = require('@apollo/gateway');
const express = require('express');

const gateway = new ApolloGateway({
  serviceList: [
    { name: 'users', url: 'http://localhost:4001/graphql' },
  ],
});

const app = express();
const server = new ApolloServer({
  gateway,
  subscriptions: false,
});

server.start().then(() => {
  server.applyMiddleware({ app });
  app.listen(4000, () => console.log('Gateway running on http://localhost:4000'));
});

				
			

Extending a Subgraph

Suppose there’s another subgraph, posts, and it extends the User type.

Code for posts Subgraph

				
					const { ApolloServer } = require('apollo-server-express');
const { buildSubgraphSchema } = require('@apollo/subgraph');
const express = require('express');
const { gql } = require('graphql-tag');

const typeDefs = gql`
  extend type User @key(fields: "id") {
    id: ID! @external
    posts: [Post!]!
  }

  type Post {
    id: ID!
    title: String!
    authorId: ID!
  }

  type Query {
    posts: [Post!]!
  }
`;

const resolvers = {
  User: {
    posts: (user) => [
      { id: '101', title: 'Post 1', authorId: user.id },
      { id: '102', title: 'Post 2', authorId: user.id },
    ],
  },
  Query: {
    posts: () => [
      { id: '101', title: 'Post 1', authorId: '1' },
      { id: '102', title: 'Post 2', authorId: '2' },
    ],
  },
};

const app = express();
const server = new ApolloServer({
  schema: buildSubgraphSchema({ typeDefs, resolvers }),
});

server.start().then(() => {
  server.applyMiddleware({ app });
  app.listen(4002, () => console.log('Posts service running on http://localhost:4002'));
});

				
			

Schema Stitching with GraphQL Tools

Installing Required Libraries

To implement schema stitching, you’ll need @graphql-tools:

				
					npm install @graphql-tools/schema @graphql-tools/stitch graphql

				
			

Combining Schemas

Let’s stitch the users and posts schemas.

Stitching Example

				
					const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeExecutableSchema } = require('@graphql-tools/schema');
const express = require('express');
const { graphqlHTTP } = require('express-graphql');

// User schema
const userTypeDefs = `
  type User {
    id: ID!
    name: String!
  }
  type Query {
    users: [User!]!
  }
`;

const userResolvers = {
  Query: {
    users: () => [
      { id: '1', name: 'Alice' },
      { id: '2', name: 'Bob' },
    ],
  },
};

// Post schema
const postTypeDefs = `
  type Post {
    id: ID!
    title: String!
    authorId: ID!
  }
  type Query {
    posts: [Post!]!
  }
`;

const postResolvers = {
  Query: {
    posts: () => [
      { id: '101', title: 'Post 1', authorId: '1' },
      { id: '102', title: 'Post 2', authorId: '2' },
    ],
  },
};

// Combine schemas
const stitchedSchema = stitchSchemas({
  subschemas: [
    makeExecutableSchema({ typeDefs: userTypeDefs, resolvers: userResolvers }),
    makeExecutableSchema({ typeDefs: postTypeDefs, resolvers: postResolvers }),
  ],
});

// Create Express app
const app = express();
app.use('/graphql', graphqlHTTP({ schema: stitchedSchema, graphiql: true }));

app.listen(4003, () => console.log('Stitched API running on http://localhost:4003/graphql'));

				
			
FeatureFederationSchema Stitching
DecentralizationDistributed schema with separate servicesCentralized schema combination
ComplexityHigher (requires resolvers for extensions)Moderate (combines schemas directly)
ToolingApollo Federation-specific toolsGeneral GraphQL tooling

Advanced Topics

Federation Directives

  • @key: Defines unique identifiers in a subgraph.
  • @external: Indicates fields managed by other subgraphs.
  • @requires: Fetches dependent fields for computation.

Optimizing Federation Performance

  • Use batching with libraries like DataLoader.
  • Cache frequently accessed data with tools like Redis.

GraphQL Federation and Schema Stitching provide powerful ways to manage and integrate GraphQL APIs in Express.js. Federation is ideal for large-scale, service-oriented systems, while Schema Stitching offers a simpler, centralized approach. By understanding these concepts and applying the techniques demonstrated in this chapter, developers can build flexible, scalable APIs tailored to their application architecture. Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India