Real-time GraphQL Subscriptions with .NET 8 Minimal APIs

Mahmut Sarıkaya 4 dk okuma 8 Görüntülenme 0
Real-time GraphQL Subscriptions with .NET 8 Minimal APIs

Why real‑time data matters for modern APIs

Imagine a dashboard that updates the moment a new order is placed, without a page refresh. Users expect instant feedback, and GraphQL subscriptions provide exactly that, but only when the underlying infrastructure can push updates efficiently. Combining .NET 8 Minimal APIs, HotChocolate, and Azure SignalR creates a low‑latency, scalable solution that works on Azure App Service or Kubernetes.

Prerequisites and system requirements

You need .NET 8 SDK (released November 2023), an Azure subscription with SignalR Service enabled, and a code editor such as VS Code or Rider. The target runtime is Windows Server 2022 or Linux Ubuntu 22.04 LTS. Make sure the Azure CLI is installed (az version 2.45 or newer) to provision resources from the command line.

Creating the Minimal API project

Open a terminal and run the following commands. They create a new web project, add HotChocolate and Azure SignalR packages, and restore dependencies.

dotnet new web -n RealTimeGraphQL
cd RealTimeGraphQL
dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.Subscriptions
dotnet add package Microsoft.Azure.SignalR
dotnet restore

After the restore finishes, the project folder contains a minimal Program.cs file ready for extension.

Adding HotChocolate GraphQL to the pipeline

Replace the content of Program.cs with the snippet below. It registers a query type, a subscription type, and tells HotChocolate to use the Azure SignalR backplane.

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using HotChocolate;
using HotChocolate.AspNetCore;
using HotChocolate.Subscriptions;

var builder = WebApplication.CreateBuilder(args);

// Register SignalR service for Azure backplane
builder.Services.AddSignalR().AddAzureSignalR();

// Register GraphQL server with subscription support
builder.Services.AddGraphQLServer()
    .AddQueryType()
    .AddSubscriptionType<Subscription>()
    .AddInMemorySubscriptions(); // fallback for local dev

var app = builder.Build();

app.MapGraphQL(); // exposes /graphql endpoint

app.Run();

public class Query
{
    public string Hello() => "Hello from .NET 8!";
}

public class Subscription
{
    [Subscribe]
    public string OnMessage([EventMessage] string message) => message;
}

The AddInMemorySubscriptions call is optional; in production Azure SignalR will handle the distribution of events across instances.

Configuring Azure SignalR as the subscription backplane

First, create a SignalR Service in Azure. The CLI command below provisions a Standard tier instance named realtime-graphql-signalr in the EastUS2 region.

az signalr create \
  --name realtime-graphql-signalr \
  --resource-group MyResourceGroup \
  --sku Standard_S1 \
  --unit-count 1 \
  --location EastUS2

Retrieve the connection string and add it to appsettings.Development.json:

{
  "AzureSignalRConnectionString": "Endpoint=https://realtime-graphql-signalr.service.signalr.net;AccessKey=...;Version=1.0;"
}

Back in Program.cs, bind the configuration value:

builder.Services.AddSignalR().AddAzureSignalR(options =>
    options.ConnectionString = builder.Configuration["AzureSignalRConnectionString"]);

HotChocolate automatically detects the SignalR backplane when the SignalR service is present, so subscription events are broadcast to every connected client regardless of the number of API instances.

Testing the subscription locally

Run the application with dotnet run. Open two browser tabs and navigate to https://localhost:5001/graphql. Using the GraphQL Playground, execute the following subscription:

subscription {
  onMessage
}

In a third tab, trigger a mutation (you can add a simple mutation to the server) that publishes a message:

public class Mutation {
    public async Task<bool> PublishMessage(string message, [Service] ITopicEventSender sender) {
        await sender.SendAsync(nameof(Subscription.OnMessage), message);
        return true;
    }
}

After adding .AddMutationType<Mutation>() to the GraphQL builder, run the mutation:

mutation {
  publishMessage(message: "Order #1234 created")
}

Both subscription tabs instantly display the new message, confirming that Azure SignalR is relaying events correctly.

Performance tuning and best practices

1. **Scale out with Azure App Service** – set the instance count to at least 2; SignalR will handle load balancing without sticky sessions.
2. **Use the Azure SignalR Service SKU that matches your traffic** – a Standard_S1 tier supports up to 1,000 concurrent connections, while Premium tiers go beyond 10,000.
3. **Enable HTTP/2** – .NET 8’s Kestrel server automatically negotiates HTTP/2, reducing latency for GraphQL over WebSockets.
4. **Monitor with Azure Monitor** – track the SignalRMessagesSent metric to detect bottlenecks early.

Conclusion

By pairing .NET 8 Minimal APIs with HotChocolate’s subscription engine and Azure SignalR’s managed backplane, developers can deliver real‑time GraphQL experiences that scale from a single dev box to a global cloud deployment. The code stays concise, the infrastructure is fully managed, and the latency stays in the low‑millisecond range—exactly what modern interactive applications demand.

Sources

Microsoft Docs – Azure SignalR Service
HotChocolate Documentation – Subscriptions
Azure CLI Reference – az signalr create

Author: Mahmut Sarıkaya — sarikayadev.com

Etiketler: #.NET 8 #GraphQL #HotChocolate #Subscriptions #Azure SignalR
Paylaş:
M

Yazar

Mahmut Sarıkaya

yazılım Geliştirici

Yorumlar

Henüz yorum yok. İlk yorumu siz yapın!

Yorum Bırakın

6 + 0 =