0
# Federation Support
1
2
Apollo Federation capabilities for building distributed GraphQL architectures with reference resolvers and federated schema generation. This module enables creating microservice-based GraphQL systems where multiple services contribute to a unified GraphQL schema.
3
4
## Capabilities
5
6
### Federation Factory
7
8
Core factory service for creating federated GraphQL schemas that can be combined with other federated services.
9
10
```typescript { .api }
11
/**
12
* Injectable factory for creating federated GraphQL schemas
13
* Extends GraphQLFactory with federation-specific capabilities
14
*/
15
export class GraphQLFederationFactory {
16
/**
17
* Merge the generated schema with an existing federated schema
18
* @param schema - Existing GraphQL schema to merge with
19
* @returns Merged federated schema
20
*/
21
mergeWithSchema(schema: GraphQLSchema): GraphQLSchema;
22
23
/**
24
* Create a federated schema from module options
25
* @param options - GraphQL module configuration options
26
* @returns Promise resolving to federated GraphQL schema
27
*/
28
create(options: GqlModuleOptions): Promise<GraphQLSchema>;
29
30
/**
31
* Transform a regular schema into a federated subgraph schema
32
* @param schema - Regular GraphQL schema
33
* @returns Federated subgraph schema
34
*/
35
transformSchemaToFederated(schema: GraphQLSchema): GraphQLSchema;
36
}
37
```
38
39
**Usage Examples:**
40
41
```typescript
42
import { Module } from "@nestjs/common";
43
import { GraphQLFederationModule } from "@nestjs/graphql";
44
import { ApolloFederationDriver, ApolloFederationDriverConfig } from "@nestjs/apollo";
45
46
// Configure federated GraphQL module
47
@Module({
48
imports: [
49
GraphQLFederationModule.forRoot<ApolloFederationDriverConfig>({
50
driver: ApolloFederationDriver,
51
autoSchemaFile: {
52
federation: 2, // Use Apollo Federation v2
53
},
54
}),
55
],
56
providers: [UserResolver, PostResolver],
57
})
58
export class FederatedAppModule {}
59
60
// Async federation configuration
61
@Module({
62
imports: [
63
GraphQLFederationModule.forRootAsync<ApolloFederationDriverConfig>({
64
driver: ApolloFederationDriver,
65
useFactory: (configService: ConfigService) => ({
66
autoSchemaFile: {
67
federation: 2,
68
path: configService.get('SCHEMA_PATH'),
69
},
70
buildSchemaOptions: {
71
orphanedTypes: [User, Post], // Include federated entities
72
},
73
}),
74
inject: [ConfigService],
75
}),
76
],
77
})
78
export class AsyncFederatedAppModule {}
79
```
80
81
### Federation Definitions Factory
82
83
Factory for generating TypeScript definitions from federated GraphQL schemas.
84
85
```typescript { .api }
86
/**
87
* Factory for generating federation-specific TypeScript definitions
88
* Handles federated schema elements like entities and references
89
*/
90
export class GraphQLFederationDefinitionsFactory {
91
/**
92
* Generate TypeScript definitions from federated schema
93
* @param options - Options for definition generation
94
* @returns Promise that resolves when generation is complete
95
*/
96
generate(options: FederationDefinitionsGeneratorOptions): Promise<void>;
97
98
/**
99
* Generate federated entity interfaces
100
* @param schema - Federated GraphQL schema
101
* @returns Generated TypeScript interface definitions
102
*/
103
generateEntityInterfaces(schema: GraphQLSchema): string;
104
105
/**
106
* Generate reference resolver types
107
* @param schema - Federated GraphQL schema
108
* @returns Generated TypeScript type definitions for reference resolvers
109
*/
110
generateReferenceTypes(schema: GraphQLSchema): string;
111
}
112
113
/**
114
* Options for federated definitions generation
115
*/
116
interface FederationDefinitionsGeneratorOptions extends DefinitionsGeneratorOptions {
117
/** Whether to generate entity interfaces */
118
generateEntityInterfaces?: boolean;
119
/** Whether to generate reference resolver types */
120
generateReferenceTypes?: boolean;
121
/** Federation version (1 or 2) */
122
federationVersion?: 1 | 2;
123
}
124
```
125
126
### Reference Resolvers
127
128
Decorators and utilities for implementing entity reference resolution in federated schemas.
129
130
```typescript { .api }
131
/**
132
* Marks a method as a GraphQL Reference Resolver for Apollo Federation
133
* Used to resolve entity references across federated services
134
*/
135
function ResolveReference(): MethodDecorator;
136
137
/**
138
* Interface for federation reference objects
139
*/
140
interface FederationReference {
141
/** GraphQL type name */
142
__typename: string;
143
/** Entity identifier fields */
144
[key: string]: any;
145
}
146
147
/**
148
* Type for reference resolver functions
149
*/
150
type ReferenceResolverFn<T = any> = (
151
reference: FederationReference
152
) => T | Promise<T>;
153
```
154
155
**Usage Examples:**
156
157
```typescript
158
import { Resolver, ResolveReference, Directive, ObjectType, Field, ID } from "@nestjs/graphql";
159
160
// Define federated entity
161
@ObjectType()
162
@Directive('@key(fields: "id")')
163
export class User {
164
@Field(() => ID)
165
id: string;
166
167
@Field()
168
name: string;
169
170
@Field()
171
email: string;
172
173
// External field from another service
174
@Field(() => [Post])
175
@Directive('@external')
176
posts: Post[];
177
}
178
179
// Resolver with reference resolver
180
@Resolver(() => User)
181
export class UserResolver {
182
constructor(private userService: UserService) {}
183
184
// Standard queries
185
@Query(() => [User])
186
users(): Promise<User[]> {
187
return this.userService.findAll();
188
}
189
190
// Federation reference resolver
191
@ResolveReference()
192
async resolveReference(reference: { __typename: string; id: string }): Promise<User> {
193
return this.userService.findById(reference.id);
194
}
195
196
// Field resolver for federated field
197
@ResolveField(() => String)
198
displayName(@Parent() user: User): string {
199
return `${user.name} (${user.email})`;
200
}
201
}
202
203
// Extending external entity from another service
204
@ObjectType()
205
@Directive('@extends')
206
@Directive('@key(fields: "id")')
207
export class Post {
208
@Field(() => ID)
209
@Directive('@external')
210
id: string;
211
212
// Add new field to external entity
213
@Field(() => Int)
214
viewCount: number;
215
216
// Field from owning service
217
@Field()
218
@Directive('@external')
219
title: string;
220
}
221
222
@Resolver(() => Post)
223
export class PostResolver {
224
constructor(private analyticsService: AnalyticsService) {}
225
226
@ResolveReference()
227
resolveReference(reference: { __typename: string; id: string }): Post {
228
// Return minimal object with external fields
229
return { id: reference.id } as Post;
230
}
231
232
@ResolveField(() => Int)
233
async viewCount(@Parent() post: Post): Promise<number> {
234
return this.analyticsService.getViewCount(post.id);
235
}
236
}
237
```
238
239
### Federation Directives
240
241
GraphQL directives used in Apollo Federation for schema composition.
242
243
```typescript { .api }
244
/**
245
* Key directive - marks fields that uniquely identify an entity
246
* @param fields - Field names that form the key
247
*/
248
const KeyDirective = '@key(fields: string)';
249
250
/**
251
* External directive - marks fields that are owned by another service
252
*/
253
const ExternalDirective = '@external';
254
255
/**
256
* Requires directive - specifies external fields needed to resolve a field
257
* @param fields - External field names required
258
*/
259
const RequiresDirective = '@requires(fields: string)';
260
261
/**
262
* Provides directive - specifies external fields that this field can provide
263
* @param fields - External field names provided
264
*/
265
const ProvidesDirective = '@provides(fields: string)';
266
267
/**
268
* Extends directive - indicates that this type extends an entity from another service
269
*/
270
const ExtendsDirective = '@extends';
271
272
/**
273
* Shareable directive (Federation v2) - marks fields that can be resolved by multiple services
274
*/
275
const ShareableDirective = '@shareable';
276
277
/**
278
* Override directive (Federation v2) - overrides field resolution from another service
279
* @param from - Service name to override from
280
*/
281
const OverrideDirective = '@override(from: string)';
282
```
283
284
**Federation Directive Examples:**
285
286
```typescript
287
import { ObjectType, Field, ID, Directive } from "@nestjs/graphql";
288
289
// Entity with composite key
290
@ObjectType()
291
@Directive('@key(fields: "id")')
292
@Directive('@key(fields: "email")')
293
export class User {
294
@Field(() => ID)
295
id: string;
296
297
@Field()
298
email: string;
299
300
@Field()
301
name: string;
302
}
303
304
// Extending external entity with requirements
305
@ObjectType()
306
@Directive('@extends')
307
@Directive('@key(fields: "id")')
308
export class Product {
309
@Field(() => ID)
310
@Directive('@external')
311
id: string;
312
313
@Field()
314
@Directive('@external')
315
name: string;
316
317
@Field()
318
@Directive('@external')
319
price: number;
320
321
// This field requires external fields
322
@Field()
323
@Directive('@requires(fields: "name price")')
324
displayPrice: string;
325
}
326
327
// Federation v2 shareable field
328
@ObjectType()
329
@Directive('@key(fields: "id")')
330
export class User {
331
@Field(() => ID)
332
id: string;
333
334
@Field()
335
@Directive('@shareable')
336
name: string; // Can be resolved by multiple services
337
338
@Field()
339
@Directive('@override(from: "legacy-service")')
340
email: string; // Override resolution from legacy service
341
}
342
```
343
344
### Federation Configuration
345
346
Configuration options specific to federated GraphQL schemas.
347
348
```typescript { .api }
349
/**
350
* Federation-specific module options
351
*/
352
interface FederationGqlModuleOptions extends GqlModuleOptions {
353
/** Auto schema file configuration for federation */
354
autoSchemaFile?: boolean | FederationAutoSchemaFileConfig;
355
356
/** Federation version to use */
357
federationVersion?: 1 | 2;
358
359
/** Whether to print federated schema SDL */
360
printFederatedSchema?: boolean;
361
}
362
363
/**
364
* Auto schema file configuration for federation
365
*/
366
interface FederationAutoSchemaFileConfig {
367
/** Path to write the federated schema */
368
path?: string;
369
/** Federation version */
370
federation?: 1 | 2;
371
}
372
373
/**
374
* Build schema options with federation support
375
*/
376
interface FederationBuildSchemaOptions extends BuildSchemaOptions {
377
/** Federation version */
378
federationVersion?: 1 | 2;
379
/** Whether to include federation directives */
380
includeFederationDirectives?: boolean;
381
}
382
```
383
384
### Federation Gateway Integration
385
386
Utilities for integrating with Apollo Federation Gateway.
387
388
```typescript { .api }
389
/**
390
* Configuration for Apollo Federation Gateway integration
391
*/
392
interface FederationGatewayConfig {
393
/** List of federated services */
394
serviceList: FederatedService[];
395
/** Enable managed federation */
396
managed?: boolean;
397
/** Schema registry configuration */
398
schemaConfigDeliveryEndpoint?: string;
399
}
400
401
/**
402
* Federated service configuration
403
*/
404
interface FederatedService {
405
/** Service name */
406
name: string;
407
/** Service GraphQL endpoint URL */
408
url: string;
409
/** Optional headers for service requests */
410
headers?: Record<string, string>;
411
}
412
```
413
414
**Gateway Integration Example:**
415
416
```typescript
417
import { ApolloGateway } from "@apollo/gateway";
418
import { ApolloServer } from "apollo-server-express";
419
420
// Configure federation gateway
421
const gateway = new ApolloGateway({
422
serviceList: [
423
{ name: 'users', url: 'http://localhost:4001/graphql' },
424
{ name: 'posts', url: 'http://localhost:4002/graphql' },
425
{ name: 'comments', url: 'http://localhost:4003/graphql' },
426
],
427
});
428
429
// Create Apollo Server with gateway
430
const server = new ApolloServer({
431
gateway,
432
subscriptions: false, // Subscriptions not supported in federation
433
});
434
435
// Start federated gateway
436
server.listen({ port: 4000 }).then(({ url }) => {
437
console.log(`๐ Federation Gateway ready at ${url}`);
438
});
439
```
440
441
### Error Handling in Federation
442
443
Best practices for handling errors in federated GraphQL architectures.
444
445
```typescript { .api }
446
/**
447
* Federation-specific error types
448
*/
449
interface FederationError extends GraphQLError {
450
/** Service that generated the error */
451
service?: string;
452
/** Whether error should be propagated to parent */
453
propagate?: boolean;
454
}
455
456
/**
457
* Error handling options for federation
458
*/
459
interface FederationErrorHandling {
460
/** How to handle service unavailability */
461
serviceUnavailable?: 'fail' | 'partial' | 'ignore';
462
/** Timeout for service requests */
463
timeout?: number;
464
/** Retry configuration */
465
retry?: {
466
attempts: number;
467
delay: number;
468
};
469
}
470
```