Step‑by‑step guide to implementing GraphQL Federation with Apollo Server 4 in a TypeScript Nx monorepo

User avatar placeholder
Written by Tamzid Ahmed

September 25, 2026

In modern micro‑frontend and micro‑service environments, GraphQL Federation with Apollo Server 4 in Nx monorepo offers a clean way to stitch multiple GraphQL services into a single unified API. This guide walks you through the entire process, from initializing an Nx workspace to exposing a federated gateway, all written in TypeScript.

Why choose GraphQL Federation with Apollo Server 4 in an Nx monorepo?

Federation enables independent teams to own their schemas while presenting a single endpoint to consumers. Combining it with Nx gives you powerful build caching, affected‑project detection, and consistent TypeScript tooling across services.

Prerequisites and Nx workspace setup

Before diving in, make sure you have the following installed:

  • Node.js 20 LTS
  • npm 9 or Yarn 4
  • npx (bundled with Node)
  • Git for version control

Run the commands below to create a new Nx workspace tailored for TypeScript:

npx create-nx-workspace@latest federated‑api 
  --preset=empty 
  --npmScope=company 
  --style=none 
  --packageManager=npm
cd federated‑api
npm install -D typescript @nrwl/node @nrwl/react @nrwl/express

Enable the @nrwl/graphql plugin (experimental) to simplify GraphQL code generation:

npm install -D @nrwl/graphql graphql

Creating the first federated service – User service

Inside the monorepo, generate a Node library that will host the User service:

npx nx g @nrwl/node:library user-service --publishable --importPath=@company/user-service

Install Apollo Server 4 and federation utilities:

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

Define the federated schema

Create libs/user-service/src/schema.ts with the following content:

import { gql } from 'graphql-tag';

export const typeDefs = gql`
  extend type Query {
    me: User @shareable
  }

  type User @key(fields: "id") {
    id: ID!
    name: String!
    email: String!
  }
`;

Resolver implementation

Implement resolvers that respect the @key directive for entity reference:

export const resolvers = {
  Query: {
    me: () => ({ id: '1', name: 'Jane Doe', email: 'jane@company.com' })
  },
  User: {
    __resolveReference(user: { id: string }) {
      // In a real app, fetch from DB by ID
      return { id: user.id, name: 'Jane Doe', email: 'jane@company.com' };
    }
  }
};

Expose the service with Apollo Server

Update libs/user-service/src/main.ts:

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { buildSubgraphSchema } from '@apollo/subgraph';
import { typeDefs, resolvers } from './schema';

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

startStandaloneServer(server, { listen: { port: 4001 } }).then(({ url }) => {
  console.log(`🚀 User service ready at ${url}`);
});

Configuring the Apollo Gateway

The gateway composes the federated schemas at runtime. Generate another Node application for the gateway:

npx nx g @nrwl/node:application gateway --publishable --importPath=@company/gateway

Install the gateway packages:

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

Gateway bootstrap file

Create apps/gateway/src/main.ts with the following logic:

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { ApolloGateway } from '@apollo/gateway';

const gateway = new ApolloGateway({
  // List each federated service endpoint
  serviceList: [
    { name: 'user', url: 'http://localhost:4001' },
    // Add additional services here
  ]
});

const server = new ApolloServer({
  gateway,
  // Required for federation
  plugins: [{ async serverWillStart() { console.log('Gateway ready'); } }]
});

startStandaloneServer(server, { listen: { port: 4000 } }).then(({ url }) => {
  console.log(`🚀 Gateway running at ${url}`);
});

Connecting everything inside the Nx monorepo

Leverage Nx’s affected commands so that only changed services are rebuilt. Add the following to nx.json:

{
  "npmScope": "company",
  "implicitDependencies": {
    "gateway": ["user-service"]
  },
  "targetDefaults": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}

Now run the two services concurrently using npm-run-all or concurrently:

npm install -D concurrently

# package.json scripts
"scripts": {
  "dev:user": "nx serve user-service",
  "dev:gateway": "nx serve gateway",
  "dev": "concurrently "npm run dev:user" "npm run dev:gateway""
}

Testing the federated schema

Open http://localhost:4000/graphql in Apollo Sandbox and run a query that spans services:

{
  me {
    id
    name
    email
  }
}

The gateway resolves me from the User service, proving successful federation.

Production‑ready considerations

  • Health checks: Expose /healthz endpoints on each service and let the gateway retry on failures.
  • Schema caching: Enable Apollo’s built‑in schema‑registry or use apollo-server-plugin-base to reduce startup latency.
  • Versioning: Keep each federated service on its own Git branch; Nx’s affected graph helps with safe releases.
  • Security: Apply JWT validation at the gateway level and forward the user context to sub‑services.

Conclusion

Implementing GraphQL Federation with Apollo Server 4 in Nx monorepo gives you a modular, type‑safe architecture that scales with team size. By following the steps above—setting up the workspace, creating federated services, wiring the gateway, and adding production safeguards—you’ll deliver a robust GraphQL API that’s easy to maintain and fast to evolve.

Ready to take it further? Add automated tests with jest‑graphql and integrate CI pipelines to catch schema breaking changes before they reach production.

Leave a Comment