Blazor Server vs WebAssembly vs Auto: Choosing the Right Render Mode
.NET 8 unified Blazor's hosting models into a single project template with three render modes: Server, WebAssembly, and Auto. If you've been putting off understanding the differences, now is the time. Each mode has real trade-offs that affect latency, scalability, and developer experience.
The Three Render Modes
Interactive Server
Server mode runs your component logic on the server. UI updates travel over a SignalR WebSocket connection. The browser receives only DOM diffs — no .NET code is ever downloaded to the client.
@rendermode InteractiveServer
Strengths: Fast initial load, full access to server-side resources (databases, file system, internal APIs), and no exposure of application logic to the client. Weaknesses: Every interaction requires a round trip. If your server goes down or the WebSocket disconnects, the UI freezes. Each connected user consumes server memory.
Interactive WebAssembly
WebAssembly mode downloads the .NET runtime and your application DLLs to the browser. Everything runs client-side after the initial load.
@rendermode InteractiveWebAssembly
Strengths: Once loaded, interactions are instant with no server dependency. Works offline if you configure it as a PWA. Scales effortlessly because the server is only serving static files. Weaknesses: The first load is heavy — expect several megabytes of downloads. You cannot access server resources directly; you need to call APIs instead.
Interactive Auto
Auto mode is the pragmatic middle ground. It uses Server mode on the first visit while the WebAssembly assets download in the background. On subsequent visits, it switches to WebAssembly.
@rendermode InteractiveAuto
Strengths: Fast first load like Server, then full client-side performance on return visits. Weaknesses: You must write components that work in both environments. Any code that touches server-only resources (like DbContext) cannot live directly in Auto-rendered components.
Setting Render Modes
You can set render modes at the component level or globally. To set a global default, configure it in App.razor:
<Routes @rendermode="InteractiveServer" />
For per-component control, apply the attribute directly:
@page "/dashboard"
@rendermode InteractiveWebAssembly
<h1>Dashboard</h1>
<p>This component always runs in WebAssembly.</p>
You can also apply render modes from a parent component:
<MyWidget @rendermode="InteractiveServer" />
One critical rule: a child component cannot request a "higher" interactivity mode than its parent. A static parent cannot host an interactive child without an explicit render mode boundary.
Per-Page Render Modes
A common pattern in .NET 8 is to use static server-side rendering (SSR) by default and opt individual pages into interactivity. This gives you the best of both worlds — fast, SEO-friendly pages where you don't need interactivity, and rich interactive components where you do.
@page "/settings"
@rendermode InteractiveServer
<EditForm Model="settings" OnValidSubmit="Save">
<InputText @bind-Value="settings.DisplayName" />
<button type="submit">Save</button>
</EditForm>
@code {
private UserSettings settings = new();
private async Task Save()
{
// Direct database access — only works in Server mode
await db.SaveChangesAsync();
}
}
How to Choose
Start with these questions:
- Do you need SEO? Use static SSR for public-facing pages.
- Do you need direct server resource access? Use Server mode.
- Do you need offline support? Use WebAssembly.
- Do you want fast first loads and responsive subsequent visits? Use Auto.
For most line-of-business applications, Server mode remains the simplest choice. You avoid the complexity of API layers and get immediate access to your database and services. The scalability concern is real but manageable — a single server can handle thousands of concurrent SignalR connections.
For public-facing applications where latency matters and you're already building APIs, WebAssembly or Auto mode makes more sense.
A Practical Recommendation
Don't overcomplicate it. Start with static SSR as your default. Add InteractiveServer to the specific components that need interactivity. If you later find that server load is a problem or you need offline capabilities, migrate those components to Auto or WebAssembly. The render mode system is designed to let you make this decision per-component, so you rarely need to commit to one mode for the entire application.