Blazor in production: real limits and architecture
Matteo Migliore

Matteo Migliore is an entrepreneur and software architect with over 25 years of experience developing .NET-based solutions and evolving enterprise-grade application architectures.

He has led enterprise projects, trained hundreds of developers, and helped companies of all sizes simplify complexity by turning software into profit for their business.

Luca works at a software house in Bologna and has just received a request he knows well: rewrite an internal business application, eight years old, built in ASP.NET MVC with jQuery scattered everywhere. The client wants a modern, reactive interface, and wants it by the end of the year. The team is made of four developers solid on C# and .NET, but none of them is a frontend specialist. The question circulating in the office for a week has been the same: do we build it in React, in Angular, or do we finally try Blazor?

It is the same question I receive dozens of times a year, from teams of every size. And it almost always arrives loaded with misplaced enthusiasm or unjustified skepticism. There are those who want Blazor because "finally I don't have to write JavaScript anymore", and those who avoid it because "they heard it's slow". Both positions are superficial. Blazor is a mature technology, in production in thousands of real applications, but it has precise characteristics that make it excellent in some scenarios and inadequate in others.

This article is not an introductory tutorial nor a marketing piece. It is the pragmatic guide I wish I had before taking Blazor to production on real projects: what changes between the different rendering models, what the real performance is (not the toy benchmarks), how to handle SEO and authentication, when it is worth it compared to React and Angular, and which mistakes I see recurring in teams adopting it for the first time. All in the context of .NET and the Italian market in 2026.

Is Blazor really production-ready in 2026?

Let's start with the question that blocks many teams before they even begin. The short answer is yes, and not since yesterday. Blazor has been in production in real enterprise applications since .NET 5, and with .NET 8 and .NET 9 it has reached a maturity that makes it a solid choice for business applications, internal portals, dashboards and line-of-business software.

The point is that "production-ready" does not mean "suitable for any scenario". Blazor is a family of technologies, not a monolithic product, and its suitability depends entirely on what you need to build. An internal business application used by 300 employees behind corporate authentication is an ideal scenario. A public e-commerce site with millions of monthly visitors and aggressive SEO requirements is a scenario where Blazor requires far more attention and where other technologies may be more appropriate.

The important thing to understand is that the historical criticisms of Blazor, excessive download weight, SEO problems, interaction latency, were tied to specific versions and specific rendering models. With the unification introduced in .NET 8, most of those limits now have a concrete solution within the same framework. Anyone judging Blazor based on a 2021 article is judging a technology that no longer exists in the same form.

If you want a general overview of the technology before diving into the operational details, we have a dedicated page explaining what Blazor is and how it fits into the .NET ecosystem. Here, instead, we go straight to what you need to know to take it to production without surprises.

The four Blazor rendering models: Server, WebAssembly, Auto and SSR

This is the most important architectural decision you will make with Blazor, and the source of most of the confusion. Unlike React or Angular, where the execution model is essentially just one (JavaScript code running in the browser), Blazor offers you four different ways to run the same components. Choosing well makes the difference between a project that flies and one that frustrates users and teams.

Blazor Server: the logic stays on the server

In Blazor Server, components run on the server. The browser receives only a light initial page and a persistent SignalR connection acting as a bridge: every click, every keystroke, every interface event travels to the server, is processed there, and the server sends back to the browser only the interface diff to apply. The advantage is clear: the initial download is minimal, the code never leaves the server, and you have direct access to databases and backend services without exposing APIs. The downside is equally clear: every interaction requires a network round-trip, so responsiveness depends on latency, and the server keeps the state of every connected user in memory, which weighs on scalability.

Blazor Server is the natural choice for internal applications, where users are on a low-latency network and the number of simultaneous connections is predictable. For a business application used by a few hundred employees it is often the simplest and most effective solution.

Blazor WebAssembly: everything in the browser

In Blazor WebAssembly the entire application, including the .NET runtime, is downloaded into the browser and executed client-side via WebAssembly. After the initial load, the application works offline, does not load the server for UI interactions, and behaves like a true Single Page Application. The price is the heavier initial download, because the browser must download the runtime and the application assemblies, and the fact that the code runs on the client, so any sensitive logic or data access must go through exposed and protected APIs.

Auto: the best of both worlds

The Auto mode, introduced with .NET 8, is Microsoft's attempt to solve the dilemma. On first access the component is served in Server mode, so the user gets immediate responsiveness without waiting for the runtime download. Meanwhile, in the background, the browser downloads the WebAssembly bundles. On subsequent visits the component runs entirely client-side. It is a great option for applications that want a fast start and then independence from the server, but it adds complexity: the same page can run in two different contexts, and you must write code that works in both.

Static SSR: server rendering without persistent interactivity

Static server rendering, also from .NET 8, renders components as full HTML on the server and sends it to the browser without maintaining any persistent connection. It is perfect for public pages, SEO-oriented content, landing pages and anything that does not require rich interactivity. Combined with Enhanced Navigation and Stream Rendering, it gives the feel of a SPA while remaining, at its core, server rendering. With .NET 8 you can mix all four models in the same project, deciding the rendering page by page or even component by component.

In practice, a typical choice for a modern application is: static SSR for public and marketing pages, and Server or Auto interactivity for the application areas behind login. This is the level of flexibility that simply did not exist up to .NET 7.

NET developer comparing Blazor Server, WebAssembly, Auto and SSR rendering models

How the rendering model is declared in code

One of the things I appreciate most about the .NET 8 unified model is how explicit it is. You don't have to create separate projects to choose the rendering: you decide it with an attribute on the component. This makes architectural decisions readable directly in the code, which is valuable as the project grows and new developers join the team.

// Public page, static server rendering only for SEO
@page "/catalog"

// Interactive client-side application area
@page "/dashboard"
@rendermode InteractiveWebAssembly

// Auto mode: starts in Server, then switches to WebAssembly
@page "/orders"
@rendermode InteractiveAuto

The simplicity is deceptive, though. The fact that a single attribute changes the rendering model does not mean the consequences are trivial. A component marked as interactive WebAssembly can no longer access the Entity Framework DbContext directly, because it runs in the browser. An interactive Server component maintains a persistent connection that weighs on server memory. Understanding where the code runs, and therefore what it can and cannot do, is the fundamental skill for using Blazor in production without incidents.

A frequent mistake in beginner teams is marking the entire application as interactive, "to be safe", ending up paying the costs of all rendering models without the benefits of any. The pragmatic rule is: start from static rendering, and enable interactivity only where the user experience truly requires it.

Real Blazor performance in production: what to actually measure

Discussions about Blazor performance are often a theater of useless benchmarks. It matters little how fast it renders a million rows in a synthetic loop. What matters enormously is how the real application behaves, with your data, on your users' devices, on their connection. Let's look at the metrics that really count.

First load time

This is the historical weak point of Blazor WebAssembly. A WebAssembly application on .NET 8, with aggressive trimming, partial ahead-of-time compilation and Brotli compression, typically downloads between 2 and 5 MB on first access, against roughly 1-2 MB for an equivalent React SPA. For internal applications, where users access every day and the payload is cached, this is rarely a real problem. For public sites where every visitor is new, it must be measured and optimized carefully, or avoided in favor of server rendering.

Blazor Server, on the contrary, has a very light first load, because the browser only downloads HTML and the SignalR script. This makes it paradoxically better than WebAssembly exactly where you would expect the opposite: in perceived startup speed.

Interaction latency

Here the relationship reverses. In Blazor WebAssembly, after loading, interactions are instant because everything runs locally. In Blazor Server every interaction goes through the network: with 20 milliseconds of latency the experience is smooth, with 150 milliseconds it starts to feel noticeably slow in highly reactive components like real-time typing or drag and drop. This is why Blazor Server shines on low-latency corporate networks and suffers on unstable mobile connections.

Server memory consumption

This is the metric many teams discover too late. Each user connected to a Blazor Server application maintains an active circuit on the server, with the state of their components in memory. A thousand simultaneous users means a thousand circuits. It must be sized and load-tested: it is not an insurmountable problem, but it is a variable that React and Angular simply do not have, because there the state lives in the user's browser.

The practical lesson is one: measure on the real application, not on benchmarks. Application Insights and the .NET diagnostic tools give you the numbers that count, first render time, payload size, number of active circuits, interaction response time. Deciding the rendering model without this data is betting blind.

Performance monitoring dashboard of a Blazor application in production

Blazor and SEO: the problem exists, but has a precise solution

For years "Blazor is not good for SEO" was a true statement, repeated for good reason. Pure Blazor WebAssembly renders content in the browser only after downloading the runtime and running the application. Search engine crawlers, especially those that do not run JavaScript thoroughly or impose time limits, saw a substantially empty page.

The solution, since .NET 8, is static server rendering. Pages are rendered as full HTML on the server and sent to the crawler ready to go, exactly as happens with a traditional ASP.NET MVC page or with Razor Pages. The crawler receives real, indexable content, without having to run any script. Interactivity, where needed, is added afterwards with client-side hydration, but the content for SEO is already there at the first byte.

For a public SEO-oriented site, today the correct recipe with Blazor is static server rendering plus Enhanced Navigation, enabling interactivity only in the sections that truly need it. This eliminates the historical problem and puts Blazor on the same level as a traditional server-rendered application, with the advantage of being able to use the same components also in the interactive areas.

It must be said honestly: if your product is a large public site where SEO is the primary source of traffic and every millisecond of load time affects ranking, ecosystems like Next.js still have an advantage in maturity and specific tooling. But for most .NET applications, where public pages are part of the system and not the entire product, Blazor's static SSR is more than sufficient.

Authentication and security in Blazor: where protection really lives

Authentication is one of the topics where I see the most conceptual errors, and where errors are costly because they become security vulnerabilities. The key point to internalize is that the authentication model changes radically depending on where the code runs.

Authentication in Blazor Server and server rendering

In Blazor Server and in the .NET 8 server rendering, authentication uses the standard ASP.NET Core stack: cookies, ASP.NET Core Identity or OpenID Connect against Entra ID. Tokens and credentials live on the server, handled securely, and the browser receives only a session cookie. It is the most secure and simplest model to handle correctly, because it is the same one you use in any server-side web application.

Authentication in Blazor WebAssembly

In WebAssembly the story changes. The application runs in the browser, so authentication is token-based via OAuth 2.0 and OpenID Connect, with Microsoft's dedicated library. Tokens are kept in the browser, which introduces different security considerations: the token is accessible to client code, must be protected from cross-site scripting attacks, and has a lifecycle to manage carefully through refresh tokens and short expirations.

Client-side authorization is always cosmetic

This is the point I want to stress strongly. The AuthorizeView component and the Authorize attribute work in both models and are convenient for hiding buttons and sections from those without permissions. But in WebAssembly this is only user experience, not security: the code runs in the browser and a malicious user can bypass it. The real protection must always be on the API, on the server, where the user has no control. A secure Blazor WebAssembly application has a backend that validates every request regardless of what the interface shows.

This principle is not specific to Blazor, it applies to any SPA, but in Blazor it generates confusion because the same C# logic can run both on the server and on the client, and developers used to the backend tend to trust the code even when it has migrated into the browser. The rule is simple: if it runs in the browser, it is not secure, period.

When Blazor beats React or Angular

This is the question we started with Luca, and it deserves an honest answer free of cheerleading. There is no absolute winning technology: there is the right technology for a specific team and a specific type of application.

Blazor is worth it when...

The team is already strong on C# and .NET and has no dedicated frontend specialists. In this case Blazor eliminates the cost of maintaining two separate skill sets and two separate ecosystems. It is worth it when you want to share models, validation rules and business logic between backend and frontend without rewriting them in TypeScript: you define a class with its validation attributes and use it identically on the server and on the client. It is worth it when the project is a business or line-of-business application behind authentication, where SEO does not matter and the user experience is that of a productivity application, not a showcase site.

React or Angular are worth it when...

The product is public, very high-traffic, with strict SEO requirements and every millisecond of load time has an economic impact. When you need the enormous npm ecosystem and extremely mature UI libraries for specific scenarios, from complex charts to advanced interactive maps. When the frontend team is already specialized in JavaScript and rewriting it on .NET would mean throwing away established skills. When you need to hire on the market and want a wider pool of candidates: React developers are simply more numerous.

The truth about the learning cost

An argument often underestimated in favor of Blazor is the learning cost for a .NET team. A productive C# developer becomes productive on Blazor in days, not weeks, because the mental model, the language, the tools and the debugging are the same as the backend they already know. The same developer, put on React, has to learn a new language, a new state paradigm, a new build ecosystem, and live with the continuous churn of JavaScript libraries. For many Italian companies, where teams are small and full-stack, this is a decisive factor that weighs more than any benchmark.

If you want to explore the broader picture of web development in the .NET ecosystem, beyond the single technology, you'll find useful insights in our web development course, which addresses frontend architectural choices across the board.

Development team discussing the choice between Blazor, React and Angular in front of a whiteboard

The most common mistakes when taking Blazor to production

These are not theoretical textbook errors. They are the concrete problems I see emerging in teams adopting Blazor for the first time, the ones that turn a promising project into a source of frustration.

Mistake 1: choosing the rendering model by fashion, not by context

Many teams choose WebAssembly because "it's the future" or Server because "it's simpler", without analyzing their real scenario. The choice of rendering model is an architectural decision that depends on network latency, number of simultaneous users, offline requirements, importance of first load and SEO. Choosing it by hearsay is the leading cause of disappointing Blazor projects.

Mistake 2: ignoring disconnection handling in Blazor Server

The SignalR connection of Blazor Server can drop: unstable network, computer going to sleep, timeout. When it happens, the user sees by default an unreassuring gray message and loses unsaved work. A serious Blazor Server application in production must customize the reconnection experience, handle persistence of critical state and clearly communicate to the user what is happening. Neglecting this guarantees support tickets and unhappy users.

Mistake 3: treating every component as interactive

As mentioned, marking the whole application as interactive is convenient but costly. You pay server memory with Blazor Server, or download size with WebAssembly, even for pages that only show static content. The discipline of enabling interactivity only where needed is what distinguishes a well-designed Blazor application from a heavy and slow one.

Mistake 4: not optimizing the WebAssembly payload

Publishing a Blazor WebAssembly application without trimming, without Brotli compression and without lazy loading of assemblies means serving users a much heavier download than necessary. These are standard, documented optimizations that require minimal configuration but that many teams forget, only to complain later that "Blazor is slow to load".

Mistake 5: trusting client-side logic

We saw it discussing security, but it is worth repeating because it is the most dangerous error: putting validation, permission checks or sensitive logic only on the client in WebAssembly, assuming "it's C# code anyway". The browser is hostile territory. Every rule that matters must be replicated and validated on the server.

Real cases: where Blazor delivers the best results

Theory is useful, but it is in concrete scenarios that you understand where a technology pays off. Here are the types of application where I see Blazor deliver the best results in the Italian market.

Business and line-of-business applications

This is the home turf. Software for managing orders, inventory, master data, invoicing, internal processes: applications used daily by company staff, behind authentication, where productivity matters and not the public showcase. Here Blazor Server shines for its simplicity of data access and instant loading, and .NET teams are maximally productive.

Dashboards and internal tools

Control panels, monitoring dashboards, administration tools: applications with tables, filters, charts and complex forms. The ability to reuse backend models and to write filter logic once, shared between server and interface, drastically reduces code and bugs from misalignment between frontend and backend.

Modernizing legacy applications

Many Italian companies have dated business applications in Windows Forms or WPF, or in ASP.NET MVC with jQuery, exactly like Luca's case. Blazor offers a natural migration path: the team reuses C# skills, can port much of the existing logic, and modernizes the interface without rewriting from scratch in a new language. For those coming from the desktop world, the conceptual transition from WPF components to Blazor components is surprisingly smooth.

Where Blazor is not the right choice

For honesty, I repeat it: large public very high-traffic sites with SEO as the primary source, applications requiring specialized UI libraries available only in the JavaScript ecosystem, products where the frontend team is already established on React or Angular. In these cases forcing Blazor is an ideological decision, not an engineering one.

How to prepare to use Blazor in production seriously

Reaching production with Blazor without incidents requires building some specific skills that go beyond "knowing how to write a component". Here are the areas to invest in before putting a Blazor application in users' hands.

The first is a deep understanding of the rendering models and their implications: where the code runs, what it can do in each context, how to pass data between server and client securely. It is the skill that separates those who use Blazor with awareness from those who endure it. The second is the component lifecycle and state management: understanding when a component is rendered, when it is hydrated, how changes propagate, avoids an entire category of subtle, hard-to-diagnose bugs.

The third is integration with the rest of the .NET ecosystem, because Blazor does not live in isolation: it relies on ASP.NET Core for hosting, on Entity Framework for data, on SignalR for communication, on Application Insights for observability. Mastering Blazor in production means mastering this whole, not just the component syntax. The fourth is the discipline of performance and security we discussed: measure before optimizing, and never trust the client.

Building these skills alone, by trial and error, on a production project, is possible but costly in terms of errors and time. A structured path drastically shortens the curve, because it takes you directly to the decisions that matter instead of making you discover problems when they are already in production. This is exactly the approach of our Blazor course, designed for .NET developers who want to take Blazor to production knowingly and not by hearsay. Anyone looking even just for preliminary information will find much value in carefully evaluating a structured Blazor course before improvising on a real project.

Conclusion: Blazor is an engineering choice, not an ideological one

Back to Luca and his team in Bologna: the correct answer to their question is not "use Blazor" nor "use React". It is "analyze your context and choose accordingly". In their specific case, an internal business application, a team strong on .NET without frontend specialists, no SEO requirements, the answer leans clearly toward Blazor, probably in Server or Auto mode. But it was the reasoning that led there, not fashion.

Blazor in 2026 is a mature technology, in production in thousands of real applications, with a unified rendering model that has solved most of the historical limits. It is not the answer to everything, and anyone presenting it as such is selling you something. It is instead an excellent tool when the context is right: .NET teams, line-of-business applications, the desire to stop maintaining two separate skill sets to do the same thing.

The attention points, WebAssembly bundle weight, Server disconnection handling, SEO on public content, are all real but all with known and documented solutions. Knowing them in advance is the difference between a calm adoption and a series of unpleasant surprises in production. The technology is there, it is solid, and for the Italian .NET developer it represents a concrete opportunity to stay full-stack without spreading across two ecosystems.

The training path we offer at BestDeveloper on Blazor is designed exactly for this: not to teach you the syntax you find in the documentation, but to take you to the architectural decisions that matter in production, through real cases and the experience of those who have already put Blazor in users' hands. Because the difference between a Blazor application that works and one that flies is played out right there.

Frequently asked questions

Yes. Blazor has been in production in thousands of enterprise applications since .NET 5, and with .NET 8 and .NET 9 it has reached a maturity that makes it a solid choice for business applications, internal portals, dashboards and line-of-business software. The unified rendering model introduced in .NET 8 (Server, WebAssembly, Auto and static SSR in the same project) removed most of the historical limitations. The areas that still require attention are the initial WebAssembly bundle download, disconnection handling in Blazor Server, and SEO on public content, all problems with known and documented solutions.

Blazor Server runs component logic on the server and syncs the UI with the browser through a persistent SignalR connection: the initial download is light, but every interaction requires a network round-trip and the server keeps state for each connected user. Blazor WebAssembly downloads the .NET runtime and the app into the browser and runs everything client-side: after the initial load it works offline and offloads the server, but the first download is heavier. With .NET 8 there is also the Auto mode, which starts in Server for immediate responsiveness and switches to WebAssembly after downloading the bundles in the background.

It depends on the rendering model. Pure Blazor WebAssembly renders in the browser after loading the runtime, so it is problematic for crawlers that do not run JavaScript for long and for indexing times. The solution introduced in .NET 8 is static server-side rendering (SSR): pages are rendered as full HTML on the server and sent to the crawler ready to go, with interactivity added afterwards if needed. For a public SEO-oriented site, today you use static SSR plus Enhanced Navigation and enable interactivity only where it is needed. For applications behind login, SEO is irrelevant and any model works.

Blazor is a better choice when the team is already strong in C# and .NET, when you want to share models and validation logic between backend and frontend without rewriting them, and when the project is a business or line-of-business application behind authentication. React and Angular are often still preferable for public, very high-traffic products with strict SEO requirements, for apps that need the npm ecosystem and mature UI libraries, or when the frontend team already specializes in JavaScript. The choice is contextual: there is no absolute winner, there is the right technology for the team and the type of application.

A Blazor WebAssembly application on .NET 8 with partial ahead-of-time compilation, aggressive trimming and Brotli compression typically downloads between 2 and 5 MB on first access, against roughly 1-2 MB for an equivalent React SPA. The payload is then cached and subsequent loads are nearly instant. Runtime trimming, lazy loading of assemblies for less-used areas and server-side pre-rendering significantly reduce perceived first-render time. For internal applications the initial weight is rarely a problem; for high-traffic public sites it must be measured and optimized carefully.

In Blazor Server and in the .NET 8 server rendering, authentication uses the standard ASP.NET Core stack: cookies, ASP.NET Core Identity or OpenID Connect against Entra ID, with tokens handled securely server-side. In Blazor WebAssembly authentication is token-based (OAuth 2.0 and OpenID Connect via the Microsoft.AspNetCore.Components.WebAssembly.Authentication library), with tokens kept in the browser and therefore different security considerations. The AuthorizeView component and the Authorize attribute work in both models, but client-side authorization must always be treated as cosmetic: the real protection has to live on the API.

Leave your details in the form below

Matteo Migliore

Matteo Migliore is an entrepreneur and software architect with over 25 years of experience developing .NET-based solutions and evolving enterprise-grade application architectures.

Throughout his career, he has worked with organizations such as Cotonella, Il Sole 24 Ore, FIAT and NATO, leading teams in developing scalable platforms and modernizing complex legacy ecosystems.

He has trained hundreds of developers and supported companies of all sizes in turning software into a competitive advantage, reducing technical debt and achieving measurable business results.

Stai leggendo perché vuoi smettere di rattoppare software fragile.Scopri il metodo per progettare sistemi che reggono nel tempo.