TL;DR: Struggling with laggy dashboards and delayed updates? Traditional REST APIs can’t handle real-time data efficiently. This guide shows how Blazor with gRPC streaming delivers lightning-fast, server-driven updates for responsive dashboards. Learn implementation steps, performance tuning, and best practices for scalable .NET apps.
Real-time dashboards aren’t optional, they’re critical for applications where every second counts. Think stock trading, health monitoring, or delivery tracking. A single missed update can cost money, jeopardize safety, or delay shipments.
Traditional REST APIs struggle with continuous updates because they rely on polling, which adds latency and overhead. gRPC server-streaming solves this by pushing low-latency updates directly to the browser over an always-open connection.
In this guide, you’ll combine Blazor’s component model with gRPC server-streaming to build dashboards that stay in sync with live data. We’ll cover
Real-time streaming requires two parts working together:
You’ll create both projects, add references, and configure Kestrel for HTTP/2 with TL.
Open a new terminal in an empty directory and run these commands to scaffold your solution: a Blazor Server front-end for the UI and a gRPC back-end for real-time data streaming:
dotnet new sln -n RealTimeDashboard
dotnet new blazorserver -n DashboardApp
dotnet new grpc -n DashboardGrpc
dotnet sln add DashboardApp/DashboardApp.csproj
dotnet sln add DashboardGrpc/DashboardGrpc.csproj
Your folder structure will look like this:
RealTimeDashboard/
├─ DashboardApp/ # Blazor UI
│ └─ Program.cs
├─ DashboardGrpc/ # gRPC back end
│ └─ Program.cs
└─ RealTimeDashboard.sln
You can find the complete codebase of this application in this GitHub repository.
Blazor needs access to gRPC message types. Add a reference in DashboardGrpc.csproj file:
In the DashboardApp.csproj file, we need to configure Protobuf generation so the client and server code are auto-generated from your .proto file:
In DashboardGrpc.csproj file, add this code:
These settings instruct the build process to:
gRPC requires HTTP/2, and browsers demand TLS for it. Update Program.cs in the gRPC project to enable HTTPS and HTTP/2. Then run:
Note: Run dotnet run inside DashboardGrpc to confirm the server starts with no errors.
To enable the Blazor UI to communicate with the gRPC service, you need a typed client. Follow these steps:
From the solution root, run:
cd DashboardApp
dotnet add package Grpc.Net.Client
cd .. Open DashboardApp/Program.cs and add the following client configuration:
// DashboardApp/Program.cs
builder.Services.AddGrpcClient<DashboardService.DashboardServiceClient>(options =>
{
// The same HTTPS address you opened in Program.cs of the gRPC host
options.Address = new Uri("https://localhost:5001");
}); When you press F5 (or dotnet run in the solution root), both projects start:
At this point, your environment supports a secure, always‑on stream from the gRPC server to any Blazor component. Next, you’ll add the .proto file, implement the service logic, and bind the UI to live data.
Real-time dashboards need a communication pattern that supports continuous updates without constant polling. gRPC offers four call patterns:
Here, we focus on server‑streaming because dashboards mostly consume continuous data but rarely need to push large amounts back.
Create a new file at DashboardGrpc/Protos/dashboard.proto and add the following:
context.CancellationToken for clean shutdown.Task.Delay(..., context.CancellationToken) to control update intervals and break out on cancellation.program.cs if your network drops idle connections.Now it’s time to connect your Blazor UI to the gRPC stream, consume each incoming DataPoint, and update the page in real time. You’ll start by rendering raw values, then upgrade to a chart without changing the underlying data flow.
Make sure you’ve already registered the client in Program.cs. In any Razor component, inject it like this:
@using DashboardGrpc
@inject DashboardService.DashboardServiceClient Grpc Add a new component at DashboardApp/Components/Pages/LiveData.razor:
You can plug in any Blazor chart library. For example, install Syncfusion Blazor Charts.
dotnet add package Syncfusion.Blazor.Charts Update the Razor page to render charts instead of raw lists. You can find the updated Razor component here.
In StartStream, replace StateHasChanged() with await RenderChart() to redraw the chart for each new batch of points. By separating data collection from rendering, you can switch between raw lists, tables, or charts without changing the streaming logic.
Enable gzip compression in the Program.cs:
builder.Services.AddGrpc(options =>
{
options.ResponseCompressionAlgorithm = "gzip";
options.ResponseCompressionLevel = CompressionLevel.Fastest;
}); Wrap your streaming call in a helper that retries on failures:
Use it in place of StartStream:
await RunWithRetry(ct => StartStream(ct), cts.Token); This ensures short network blips do not break your dashboard. I have already implemented this in the LiveData.razor page.
brew install k6 # macOS
choco install k6 # Windows
k6 install xk6-grpc Create a load test file load-test.js:
Run the load test:
k6 run load-test.js --vus 100 --duration 30s This simulates 100 virtual users connecting to your gRPC service for 30 seconds.
Thanks for reading! In this guide, you’ve built an end-to-end solution:
To take this further:
Apply these patterns in your next project to deliver responsive dashboards that keep pace with real‑world data.
If you’re a Syncfusion user, you can download the setup from the license and downloads page. Otherwise, you can download a free 30-day trial.
You can also contact us through our support forum, support portal, or feedback portal for queries. We are always happy to assist you!