DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • GraphQL vs REST — Which Is Better?
  • GraphQL vs REST API: Which Is Better for Your Project in 2025?
  • The Death of REST? Why gRPC and GraphQL Are Taking Over
  • Power BI Embedded Analytics — Part 1.1: Power BI Authoring Data Federation

Trending

  • Reducing RAG Hallucinations With Relationship-Aware Retrieval
  • Your AI Is Not Failing, Your Context Is
  • Getting Started With GitHub Copilot CLI for Coding Tasks
  • I Reverse-Engineered 50 API Breaches. The Same Five Mistakes Keep Appearing.
  1. DZone
  2. Data Engineering
  3. Databases
  4. How to Enable Subscription in Apollo Federation With NestJS GraphQL

How to Enable Subscription in Apollo Federation With NestJS GraphQL

By default, Apollo does not allow you to enable subscription in a federation server. Here's how to enable subscription in NestJS using Apollo GraphQL.

By 
Vinod Surendran user avatar
Vinod Surendran
·
Oct. 26, 21 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
6.8K Views

Join the DZone community and get the full member experience.

Join For Free

Setting up a GraphQL server in NestJS saves 5x-10x of the effort with vanilla NodeJS. NestJS uses the standard Apollo library for setting up GraphQL. It supports both normal and federation mode. In federation mode, we can set up GraphQL servers in every microservice, which can be aggregated using a gateway just like API-Gateway with REST services. It is a very good technique if you are running microservices and want to separate the responsibility for each service.

NestJS is one of the most powerful NodeJS frameworks available as of today. One of the cool features of NestJS is that it allows easy integration with databases, message queues, authentication, etc. Furthermore, it allows developers to create applications using NodeJS within a much stricter, robust, and flexible framework like Spring Boot/Angular.

The Problem

All this comes with some inherent caveats from the Apollo library. While setting up the federation, you cannot use a GraphQL subscription. 

You will probably see this error:
Error message screenshot. 
Apollo had come up with an approach to overcome this problem, but it overcomplicates the situation. Let's see how to tackle this problem using the features in NestJS. In the example, I am using the schema first approach. The same approach can be implemented in the code-based approach. 

The Solution

The solution to this problem is to hide the subscription-based schema for the federation server and host the subscription-based GraphQL as a separate GraphQL server. Seems very simple huh? Not that easy. We will cover the method with some simple steps. 

Step 1: Classify Schema

The primary step is to separate your GraphQL schema into different files per the below conventions. 

  1. *.graphql: for GraphQL syntax supported in both federation and normal mode
  2. *.graphql.federation: for syntax supported only in federation mode (e.g., extends)
  3. *.graphql.normal: for syntax supported only in normal mode (e.g., subscription)

Save the subscription model in any "graphql.normal" file.

Screenshot of GraphQL file.

Step 2: Configure the Server

Set up the app.module.ts with two GraphQL modules, one for the normal server and another for the federation server. We need to configure the module in such a way that only the federation module loads the .graphql.federation file and only the normal module loads the .graphql.normal file. The .graphql file has to be loaded by both modules.

TypeScript
 
  imports: [
    GraphQLModule.forRoot({
      debug: false,
      playground: true,
      path: '/graphql',
      typePaths: ['./**/*.{graphql,graphql.normal}'],
      installSubscriptionHandlers: true,
    }),
    GraphQLFederationModule.forRoot({
      debug: false,
      playground: false,
      path: '/graphql-federated',
      typePaths: ['./**/*.{graphql,graphql.federation}'],
    }),
  ],


Notice that the type paths for the two modules are different as per our convention. The normal GraphQL with subscription is now available at /graphql and the server for the federation gateway is available at /graphql-federated.

We are not spinning two servers here. It is the same express server with two middleware configured for different paths, so there will not be any performance issues.

Step 3: The Illusion

This is the most important step. There are some directives in GraphQL that only work in the federated mode and vice versa. You will finally end up writing the custom version of the GraphQL model in the federated and the normal files. This will add the headache of duplicate GraphQL models in the application.

This problem can be tackled in an easy way, using dummy directives!

  • Define a declarative for “key”
TypeScript
 
import { SchemaDirectiveVisitor } from 'apollo-server-express';
import { GraphQLField } from 'graphql';

/**
 * This is a dummy implementation of the key directive for the normal mode
 */
export class FakeKeyDirective extends SchemaDirectiveVisitor {
  /**
   * Fake Key definition
   * @param _field Field of graphql
   */
  visitFieldDefinition(_field: GraphQLField<any, any>) {
    _field.args;
  }
}


  • Include it in the module.
TypeScript
 
@Module({
  imports: [
    GraphQLModule.forRoot({
      debug: false,
      playground: true,
      path: '/graphql',
      typePaths: ['./**/*.{graphql,graphql.normal}'],
      installSubscriptionHandlers: true,

      directiveResolvers: {
        key: FakeKeyDirective,
      },
    }),
    GraphQLFederationModule.forRoot({
      debug: false,
      playground: false,
      path: '/graphql-federated',
      typePaths: ['./**/*.{graphql,graphql.federation}'],
    }),
  ],
  controllers: [AppController],
  providers: [AppService, UsersResolver, UserService],
})
export class AppModule {}


  • Define a fake implementation. This only has to work in the normal mode, so the file name has to end with “graphql.normal”
TypeScript
 
directive @key(fields: String) on OBJECT


  • Now you can define the model using the federation-supported @key directive, and the model works both in the federation and normal GraphQL server.
TypeScript
 
type Department @key(fields: "id") {  id: ID!  name: String }


Now you can start the federation gateway, which listens to the /graphql-federated, and the federation works. 

For subscription, you can use any Websocket-enabled gateways like Nginx, Istio, etc. and connect directly to the microservices

Conclusion

Yes, it is possible to enable federation and subscription for GraphQL in NestJS using a simple trick that is more efficient than the Apollo method. You can download the entire code for your reference from my Github repo.

Since you are using a separate file extension other than .graphql, your IDE won’t give the native GraphQL formatting for the graphql.normaland graphql.federation files. There is a fix for this. Just enable file associations for those extensions. 

GraphQL Federation (information technology)

Published at DZone with permission of Vinod Surendran. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • GraphQL vs REST — Which Is Better?
  • GraphQL vs REST API: Which Is Better for Your Project in 2025?
  • The Death of REST? Why gRPC and GraphQL Are Taking Over
  • Power BI Embedded Analytics — Part 1.1: Power BI Authoring Data Federation

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook