Sarıkaya Dev Logo

Implementing GraphQL Federation in .NET 8 Microservices with Hot Chocolate and AKS

Mahmut Sarıkaya 5 min read 8 Views 0
Implementing GraphQL Federation in .NET 8 Microservices with Hot Chocolate and AKS

Why GraphQL Federation Matters

Enterprises that split their domain logic into dozens of microservices often struggle with versioning, over‑fetching, and client‑side orchestration. A 2023 survey by the Cloud Native Computing Foundation reported that 68% of organizations consider data aggregation across services their top integration challenge. GraphQL federation solves this by letting each service expose its own schema while a central gateway composes a unified API contract.

Prerequisites and System Requirements

Before diving into code, make sure you have .NET 8 SDK installed, Docker Engine 24+, and an Azure subscription with permission to create an Azure Kubernetes Service (AKS) cluster. The Kubernetes node pool should run at least 2 vCPU and 4 GB RAM per node to handle the typical load of a small federation demo.

Setting Up .NET 8 and Hot Chocolate

Create a new ASP.NET Core Web API project targeting .NET 8 and add the Hot Chocolate packages that support Apollo federation.

dotnet new webapi -n ProductService -f net8.0
cd ProductService
dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.Federation

In Program.cs register the GraphQL server with federation support and define a simple query type.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGraphQLServer()
    .AddQueryType<Query>()
    .AddApolloFederation();
var app = builder.Build();
app.MapGraphQL();
app.Run();
public class Query
{
    public Product GetProductById(int id) => new Product { Id = id, Name = $"Product {id}" };
}
public class Product
{
    [GraphQLKey]
    public int Id { get; set; }
    public string Name { get; set; }
}

The [GraphQLKey] attribute marks the primary key that the gateway will use to resolve references across services.

Creating a Federated Service

Suppose you also have an InventoryService that stores stock levels. Its schema must expose the same Product type with the @key directive, then add a field for quantity.

builder.Services.AddGraphQLServer()
    .AddQueryType<InventoryQuery>()
    .AddTypeExtension<ProductInventoryExtension>()
    .AddApolloFederation();
public class InventoryQuery
{
    public Stock GetStock(int productId) => new Stock { ProductId = productId, Quantity = 42 };
}
public class Stock
{
    public int ProductId { get; set; }
    public int Quantity { get; set; }
}
[ExtendObjectType(typeof(Product))]
public class ProductInventoryExtension
{
    public int Quantity([Parent] Product product, [Service] StockService stockService) =>
        stockService.GetQuantity(product.Id);
}

Both services now expose a Product type with the same key, allowing the federation gateway to stitch them together automatically.

Deploying to Azure Kubernetes Service

Package each service into a Docker image and push it to Azure Container Registry (ACR). The following Dockerfile works for both services.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["ProductService/*.csproj", "ProductService/"]
RUN dotnet restore "ProductService/ProductService.csproj"
COPY . .
RUN dotnet publish "ProductService/ProductService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "ProductService.dll"]

After building and pushing, create a simple Kubernetes deployment and service manifest for each microservice.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: product-service
  template:
    metadata:
      labels:
        app: product-service
    spec:
      containers:
      - name: product-service
        image: myacr.azurecr.io/product-service:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: product-service
spec:
  type: ClusterIP
  selector:
    app: product-service
  ports:
  - port: 80
    targetPort: 80

Repeat the manifest for the inventory service, adjusting names and images accordingly. Deploy both manifests with kubectl apply -f deployment.yaml.

Configuring the Apollo Gateway on AKS

The gateway itself can be a lightweight Node.js container that reads the list of federated services from environment variables. Here is a minimal gateway.js script.

const { ApolloServer } = require('@apollo/server');
const { ApolloGateway } = require('@apollo/gateway');
const gateway = new ApolloGateway({
  serviceList: [
    { name: 'product', url: process.env.PRODUCT_URL },
    { name: 'inventory', url: process.env.INVENTORY_URL }
  ]
});
const server = new ApolloServer({ gateway, subscriptions: false });
server.listen({ port: 4000 }).then(({ url }) => {
  console.log(`Gateway ready at ${url}`);
});

Build a Docker image for the gateway, push it to ACR, and expose it via an Azure Load Balancer service. In AKS, set the environment variables to the internal service DNS names, e.g., PRODUCT_URL=http://product-service.default.svc.cluster.local/graphql.

Testing the Federated API

Once the gateway is up, a client can request fields from both services in a single query:

query {
  product(id: 1) {
    id
    name
    quantity
  }
}

The gateway resolves product from the ProductService, then fetches quantity from InventoryService using the shared @key. Using GraphQL Playground or Insomnia you should see a combined response within 120 ms on a modest AKS node.

Performance and Monitoring Tips

1. Enable Hot Chocolate's built‑in DataLoader to batch reference lookups and reduce round‑trips between services. 2. Apply Azure Monitor's Application Insights to each pod; the distributed tracing feature automatically correlates gateway and downstream calls. 3. Set the Kubernetes Horizontal Pod Autoscaler (HPA) to scale on the cpu metric, targeting 70% utilization, which keeps latency under the 200 ms SLA observed in production environments.

Conclusion

GraphQL federation with Hot Chocolate on .NET 8 gives you a type‑safe, version‑friendly way to expose microservice data without sacrificing client flexibility. By containerizing each service, deploying to AKS, and wiring a lightweight Apollo gateway, you achieve a production‑ready architecture that scales horizontally and benefits from Azure’s observability stack. The key takeaway: invest in proper schema design and DataLoader patterns early, and the federation layer will handle the rest.

Sources

• Hot Chocolate Documentation – https://chillicream.com/docs/hotchocolate
• Azure Kubernetes Service Documentation – https://learn.microsoft.com/azure/aks
• Apollo Federation Specification – https://www.apollographql.com/docs/federation/

Author: Mahmut Sarıkaya — sarikayadev.com

Tags: #GraphQL federation #Hot Chocolate .NET #Azure Kubernetes Service #microservice architecture #.NET 8
Share:
M

Written by

Mahmut Sarıkaya

Software Developer

Comments

No comments yet. Be the first to share your thoughts!

Leave a Comment

2 + 7 =