DEV Community

gaffleck
gaffleck

Posted on

Graphql Federation with NestJS and Apollo

As your Graphql backend grows there may come a time when you want to split the service into smaller components or microservices. This can help keep your domains isolated and speed up deployments. The really cool feature of the graphql system is federation, which will allow you to deploy isloated graphql backends and integrate them for your front-end.

Let's look at an example:

Our Domains

Let's continue with our example form last week of the system for a university. Let's say we want to integrate a finance system to track the accounts payable for our students.

Here is our model for the account balance. We link the balance to the student via student ID and track a very simple amount of data.

type accountBalance{
  outstandingBalance: Int
  paymentDue: String
  StudentId: ID

}
Enter fullscreen mode Exit fullscreen mode

Now, in order to implement the backend, we have 2 choices, we can integrate the payment system into our existing student backend or split them out into microservices. Since payments and class registrations aren't necessarily correlated, let's keep the separate.

The design will require us to deploy 3 services:

  • a registration service
  • an accounts payable service
  • a gateway service to provide a unified front-end

Let's start with the gateway and work backwards from there.

The API Gateway

Api gateways are a feature of Graphql which allow you to aggregate types across micro-services without muddying your domains. NestJS is a great platform for this. To start with let's add the student object to our balance type:

type accountBalance{
  outstandingBalance: Int
  paymentDue: String
  StudentId: ID
  Student: Student
}
Enter fullscreen mode Exit fullscreen mode

Now we need to identify how to fetch a student on our Student type, back in our first Service:

type Student @key(fields:'id'){
//
}
Enter fullscreen mode Exit fullscreen mode

now in our student resolver we need to define how to fetch a student when requested by id:

@ResolveReference()
  async resolveReference(
    reference: {
      __typename: string;
      id: string;
    },
    context: IGraphqlContext
  ) {
    const { id } = reference;
    const user = await context.loaders.studentBySelfLoader.load(id);
    return this.studentMapper.persistenceToGql(user);
  }
Enter fullscreen mode Exit fullscreen mode

Now we've defined how to fetch a student when requested by any other service we just need to link the two services together via a gateway.

Now we need to define a federation service to aggregate our domains


import {
  ApolloFederationDriver,
  ApolloFederationDriverConfig,
} from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { UsersResolver } from './users.resolver';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
      driver: ApolloFederationDriver,
      typePaths: ['**/*.graphql'],
    }),
  ],
  providers: [StudentsResolver, AccountResolver],
})
export class AppModule {}


Enter fullscreen mode Exit fullscreen mode

Top comments (0)