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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • DGS GraphQL and Spring Boot
  • Power BI Embedded Analytics — Part 1.1: Power BI Authoring Data Federation
  • Optimizing Natural Language Queries for Multi-Service Information Retrieval
  • Mastering Async Context Manager Mocking in Python Tests

Trending

  • Go 1.24+ Native FIPS Support for Easier Compliance
  • Customer 360: Fraud Detection in Fintech With PySpark and ML
  • Mastering Advanced Aggregations in Spark SQL
  • MySQL to PostgreSQL Database Migration: A Practical Case Study
  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.6K 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

  • DGS GraphQL and Spring Boot
  • Power BI Embedded Analytics — Part 1.1: Power BI Authoring Data Federation
  • Optimizing Natural Language Queries for Multi-Service Information Retrieval
  • Mastering Async Context Manager Mocking in Python Tests

Partner Resources

×

Comments
Oops! Something Went Wrong

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!