Aller au contenu

Federation

Experimental

GraphQL Federation support is experimental and may not be fully implemented. The FederationResolver is available but currently returns null in the implementation.

Federation allows you to compose multiple GraphQL services into a single unified API, enabling a microservices architecture with GraphQL.

GraphQL Federation enables:

  • Multiple Services - Each service manages its own schema
  • Unified Gateway - A gateway composes all services
  • Cross-Service Queries - Query across multiple services seamlessly
  • Service Independence - Services can be developed and deployed independently

In a federated architecture:

┌─────────────┐
│ Gateway │ ← Single entry point
└──────┬──────┘
│
┌───┴───┬─────────┬─────────┐
│ │ │ │
┌──▼──┐ ┌──▼──┐ ┌──▼──┐ ┌──▼──┐
│Prod │ │Order│ │User │ │... │
│Svc │ │Svc │ │Svc │ │ │
└─────┘ └─────┘ └─────┘ └─────┘

Type GraphQL Query provides a FederationResolver for federation support:

import { FederationResolver } from '@lib/type-graphql-query';
export const FederationResolver = <DTO extends object>(
DTOClass: ClassType<DTO>,
opts?: BaseResolverOptions,
): ClassType<ServiceResolver<DTO>> => {
// Federation resolver implementation
};

Type GraphQL Query defines a RepresentationType for federation:

type RepresentationType = {
__typename: string;
} & Record<string | symbol, unknown>;

This type is used for entity references in federated schemas.

To make an entity federated, you need to:

  1. Add Federation Directives - Use @key, @requires, @provides, @external
import { ObjectType, Field, Directive } from '@lib/type-graphql';
@ObjectType()
@Directive('@key(fields: "id")')
export class Product {
@Field()
id!: string;
@Field()
name!: string;
@Field()
@Directive('@external')
organizationId!: string;
}

Federated services need reference resolvers to resolve entities:

@Resolver(() => Product)
export class ProductResolver {
@FieldResolver(() => Product)
async _entities(
@Arg('representations') representations: RepresentationType[],
): Promise<Product[]> {
const ids = representations
.filter((r) => r.__typename === 'Product')
.map((r) => r.id as string);
return await this.productService.findByIds(ids);
}
}

The gateway composes multiple services:

import { ApolloGateway } from '@apollo/gateway';
const gateway = new ApolloGateway({
serviceList: [
{ name: 'products', url: 'http://localhost:4001/graphql' },
{ name: 'orders', url: 'http://localhost:4002/graphql' },
{ name: 'users', url: 'http://localhost:4003/graphql' },
],
});

The FederationResolver in Type GraphQL Query is currently not fully implemented. The resolver function returns null and federation features may not work as expected.

If you need federation support, you may need to:

  1. Implement custom federation resolvers
  2. Use Apollo Federation directly
  3. Wait for full implementation in Type GraphQL Query

When fully implemented, federation provides:

  • Microservices - Each service is independent
  • Scalability - Scale services independently
  • Team Autonomy - Teams can work independently on their services
  • Technology Diversity - Different services can use different technologies