Blazor Server: How to Survive 1000 Concurrent Users

Blazor Server: 1000 एक साथ उपयोगकर्ताओं को कैसे संभालें

Why Blazor Server scales differently

Every connected user holds an open SignalR WebSocket circuit on your server. That circuit stores UI state in memory. 1,000 users = 1,000 server-side state bags. MVC and Razor Pages don't have this problem — they're stateless between requests.

This is Blazor Server's superpower and its load ceiling. Handled right, it's fine at scale. Handled wrong, you run out of RAM at 300 users.

Settings that actually matter

1. Disable detailed errors in production

builder.Services.AddServerSideBlazor(opts =>
{
    opts.DetailedErrors = builder.Environment.IsDevelopment();
});

DetailedErrors = true leaks stack traces to clients AND keeps references alive for debugging. Prod should be false.

2. Cap circuit memory

builder.Services.AddServerSideBlazor(opts =>
{
    opts.DisconnectedCircuitMaxRetained = 50;          // default: 100
    opts.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(2);
    opts.MaxBufferedUnacknowledgedRenderBatches = 4;   // default: 10
});

Lower the buffers and retention. Users on flaky connections won't notice. Your RAM will.

3. Compression

builder.Services.AddResponseCompression(o =>
{
    o.MimeTypes = ResponseCompressionDefaults.MimeTypes
        .Concat(new[] { "application/octet-stream" });
});
app.UseResponseCompression();

SignalR payloads are compressible. Compression over WebSockets saves ~60% bandwidth.

Load-balancing: sticky sessions are mandatory

Blazor Server circuits are stateful. If you round-robin load-balance, users will drop mid-interaction. Configure session affinity (sticky sessions) in your load balancer — nginx uses ip_hash, Azure uses ARR Affinity cookie, Kubernetes ingress needs sessionAffinity: ClientIP.

Measure before optimising

Use dotnet-counters monitor Microsoft.AspNetCore.Components.Server to see live circuit counts. The counter connected-circuits is the magic number — each is roughly 100–500 KB depending on your component tree.

Target memory per circuit: under 200 KB. Above that, audit for captured large objects in component fields.

When Blazor Server is not the answer

If you expect 5,000+ concurrent users on a single box, switch to Blazor WebAssembly for those pages. Interactive-on-demand per-component is supported in .NET 8+. You don't have to pick one model for the whole app.

हिंदी में

Blazor Server का स्केलिंग अलग है क्योंकि हर कनेक्टेड यूज़र एक SignalR सर्किट रखता है जो सर्वर की मेमोरी में UI state स्टोर करता है।

मुख्य सेटिंग्स:

  1. प्रोडक्शन में DetailedErrors = false रखें
  2. DisconnectedCircuitMaxRetained और retention period कम करें
  3. UseResponseCompression() चालू करें — SignalR payload ~60% छोटा हो जाता है
  4. लोड बैलेंसर पर sticky sessions अनिवार्य हैं

dotnet-counters से live circuit गिनती देखें। यदि प्रति सर्किट मेमोरी 200 KB से ज़्यादा है, तो component में बड़े objects captured हो रहे हैं।

5000+ यूज़र के लिए Blazor WebAssembly पर switch करें।