Apollo Federation Subgraph Support

Learn how to create Apollo Federated subgraphs using Hot Chocolate v16.

For more about Apollo Federation concepts, see the Apollo Federation documentation. Many of the core principles referenced here are documented there.

Hot Chocolate includes an implementation of the Apollo Federation v1 specification for creating Apollo Federated subgraphs. Through Apollo Federation, you can combine multiple GraphQL APIs into a single API for your consumers.

This page describes the syntax for creating an Apollo Federated subgraph using Hot Chocolate and relates the implementation specifics to their counterpart in the Apollo Federation docs. It does not provide a thorough explanation of Apollo Federation core concepts or describe how you create a supergraph to stitch together subgraphs.

You can find example projects in Hot Chocolate examples.

Get Started

Install the HotChocolate.ApolloFederation package:

Bash
dotnet add package HotChocolate.ApolloFederation
Warning
All HotChocolate.* packages need to have the same version.

Register the Apollo Federation services:

C#
builder
.AddGraphQL()
.AddApolloFederation();

Defining an Entity

An entity is an object type that can resolve its fields across multiple subgraphs. The following examples use a Product entity.

C#
public class Product
{
[ID]
public string Id { get; set; }
public string Name { get; set; }
public float Price { get; set; }
}

Define an Entity Key

Define a key for the entity. A key serves as an identifier that uniquely locates an individual record. This is typically something like a primary key, SKU, or account number.

Use the [Key] attribute on the property or properties that serve as the key:

C#
public class Product
{
[ID]
[Key]
public string Id { get; set; }
public string Name { get; set; }
public float Price { get; set; }
}

Define a Reference Resolver

Define an entity reference resolver so that the supergraph can resolve the entity across subgraphs. Every subgraph that contributes at least one unique field to an entity must define a reference resolver.

A reference resolver must be annotated with [ReferenceResolver] and must be a public static method within the type it resolves:

C#
public class Product
{
[ID]
[Key]
public string Id { get; set; }
public string Name { get; set; }
public float Price { get; set; }
[ReferenceResolver]
public static async Task<Product?> ResolveReference(
string id,
ProductBatchDataLoader dataLoader)
{
return await dataLoader.LoadAsync(id);
}
}

Key details about [ReferenceResolver] methods:

  1. The method name does not matter, but choose a descriptive one.
  2. The parameter name and type must match the GraphQL field name of the [Key] attribute. For example, if the key field is id: ID!, the parameter must be string id.
  3. Mark the return type as nullable (T?) when using nullable reference types.
  4. If you define multiple keys, include a reference resolver for each one.
C#
public class Product
{
[Key]
public string Id { get; set; }
[Key]
public int Sku { get; set; }
[ReferenceResolver]
public static Product? ResolveReferenceById(string id)
{
// Locate the Product by its Id
}
[ReferenceResolver]
public static Product? ResolveReferenceBySku(int sku)
{
// Locate the product by SKU
}
}

We recommend using a DataLoader in reference resolvers. This helps avoid the N+1 problem.

Register the Entity

Register the type in the GraphQL schema:

C#
builder
.AddGraphQL()
.AddApolloFederation()
.AddType<Product>();

Testing Reference Resolvers

Entities with a reference resolver can be queried through the auto-generated _entities query at the subgraph level:

GraphQL
query {
_entities(representations: [{ __typename: "Product", id: "<id value>" }]) {
... on Product {
id
name
price
}
}
}

The _entities field is an internal implementation detail of Apollo Federation. API consumers should not use it directly. It is documented here for testing and validation purposes.

Referencing an Entity Type

To reference an entity defined in another subgraph, create a service type reference in a separate API project. The GraphQL type name must match, and the extended type must include at least one key that matches the source graph.

C#
[ExtendServiceType]
public class Product
{
[ID]
[Key]
public string Id { get; set; }
}
builder
.AddGraphQL()
.AddApolloFederation()
.AddType<Product>();

Create a type (e.g., Review) that references the entity, and add a reference resolver so the supergraph can traverse between the types:

C#
[ExtendServiceType]
public class Product
{
[ID]
[Key]
public string Id { get; set; }
public async Task<IEnumerable<Review>> GetReviews(ReviewRepository repo)
{
return await repo.GetReviewsByProductIdAsync(Id);
}
[ReferenceResolver]
public static Product ResolveProductReference(string id) =>
new Product { Id = id };
}

With these changes, the supergraph supports traversing from a review to a product and from a product to its reviews:

GraphQL
query {
review(id: "foo") {
id
content
product {
id
name
price
reviews {
id
content
}
}
}
}

For creating a supergraph, see the Apollo Router documentation or @apollo/gateway documentation.

Next Steps

Last updated on April 13, 2026 by Michael Staib