We've shipped production software in both Blazor and React — here's what actually broke, what surprised us, and the decision framework we use with every new client.
We didn't pick Blazor because we read a benchmark blog post. We picked it after building a wholesale ordering platform in React, then building a K-12 facility management SaaS in Blazor, and watching the day-to-day development reality play out on both. This post isn't a framework marketing piece. It's a field report — what each stack actually costs you, where each one earns its keep, and how we decide which one to recommend to a founder now.
Before we go further: we already published a post called 'Why We Build in Blazor + .NET Instead of React for Enterprise SaaS,' and if you've read it, some of our core conclusions will feel familiar. But that post was a position statement. This one is different — it's built on direct comparison work across real production deployments, with specific failure points and tradeoffs we've experienced firsthand. If you want the philosophy, read that post. If you want the war stories, keep reading.
The Two Projects We're Actually Comparing
OpsFlow is our flagship vertical SaaS product — a facility operations and work order management platform purpose-built for K-12 school districts. It's live in production across multiple districts, built entirely in Blazor Server with .NET, and deployed as a multi-tenant application with role-based access control, real-time status updates, and integrations with district HR and asset systems. The user base is maintenance technicians, directors of operations, and central office administrators — not developers, not tech-forward users.
The React project is a wholesale ordering platform we built for W.L. Petrey Wholesale, a regional wholesale distributor based in Alabama. Their sales reps and retail customers needed a way to browse inventory, place orders, manage account history, and get real-time pricing — all tied into their existing backend systems. This wasn't a greenfield API — we were integrating against an existing data layer with irregular structure. We chose React because the client had existing frontend developers who worked in JavaScript, the interface needed to feel snappy on mobile for reps in the field, and the design required a high degree of interactive component composition that the team was already fluent building in React. Both projects are in production. Both have real users. Neither was a toy.
Where React Earned Its Keep
The Petrey platform genuinely benefited from React in a few concrete ways. First, component reusability across a complex product catalog UI was fast to build once the team had established a component library. Filtering, sorting, inline quantity editing on large order grids — React's model made that composition feel natural. Second, because the client's existing developers were JavaScript-native, onboarding to the codebase was low-friction. We weren't asking anyone to context-switch into a new mental model. Third, the mobile experience mattered here. React with a well-structured state management layer gave us granular control over when and how re-renders happened, which translated to a snappier feel on lower-end Android devices that some field reps were using.
React's ecosystem is also genuinely deep. When we needed a specific data grid behavior, a date picker that worked in a particular way, or a charting component that matched a design spec, we found a well-maintained library. That's not nothing. In early product development, time spent building generic UI infrastructure is time not spent on the domain logic that actually differentiates your product.
- Highly interactive, component-dense UIs where fine-grained re-render control matters
- Teams already fluent in JavaScript/TypeScript who don't want a context switch
- Mobile-first or consumer-facing products where perceived performance on varied hardware matters
- Projects where the API layer is owned by someone else and your job is entirely frontend
- Design systems that need to be shared across multiple frontends or even mobile (React Native)
Where React Cost Us
Here's what the React posts on LinkedIn don't talk about: the coordination tax. In a .NET shop, the moment you introduce a React frontend, you've created a boundary. Every feature that touches data now requires work on both sides of that boundary — you define a DTO, expose an API endpoint, handle auth tokens, serialize/deserialize, write frontend service calls, manage loading and error states client-side. On a mature team with good discipline, this is manageable. On a team moving fast with a tight timeline, it compounds. We estimated we spent roughly 20-25% of our Petrey development time on API contract work and client-side state management plumbing that would have been zero in a Blazor Server architecture — the component would have just called a service method directly.
JWT authentication management in React also requires more active care than it gets credit for. Token storage, refresh logic, handling 401s gracefully, securing routes — none of it is hard, but all of it is code you write and code that can go wrong. On the Petrey platform we used a well-established pattern and had no security incidents, but the surface area is real. You're making decisions about token storage in the browser that have security implications, and those decisions require ongoing attention as the application grows.
Where Blazor Earned Its Keep
OpsFlow runs on Blazor Server. A maintenance technician in a school district logs in, submits a work order, and a facilities director can see it update in real-time without a page refresh. Role-based permissions control what every user sees and can do — district admin, building principal, maintenance tech, and director all have different views of the same data. None of this required us to build an API layer. We call C# service classes directly from Blazor components. The business logic lives in one place, the validation lives in one place, and when a domain rule changes, we change it once.
The security model in Blazor Server was also a genuine advantage for a K-12 enterprise product. Because the application runs server-side and communicates over a persistent SignalR connection, there are no JWTs sitting in localStorage. User data never leaves the server in a raw form that a browser can inspect. That said, we want to be precise here: Blazor Server is not magically immune to attack. The SignalR connection itself is an attack surface — an XSS vulnerability could still be used to hijack an active session, because script running in the browser can interact with that connection. The security advantage is real, but it's more accurate to say Blazor Server reduces your attack surface around token theft specifically, not that it eliminates the need for XSS protection or session security hygiene. We still enforce Content Security Policy, validate all inputs server-side, and treat the connection with the same scrutiny we'd give any persistent session.
The development velocity advantage on OpsFlow was measurable. Features that would have required API endpoint design, frontend service wiring, and client-side state management in React got built as a component and a service call. For a two-person team iterating fast on district feedback, that overhead reduction was not trivial. We could ship a new work order status workflow in an afternoon rather than a day and a half.
- Enterprise applications where the team is .NET-native and doesn't want to maintain a JavaScript competency
- Multi-tenant SaaS with complex, role-based permission models that need to be enforced at the server
- Internal-facing tools, ops dashboards, and admin portals where millisecond UI latency is not a user experience differentiator
- Products where the domain logic is complex and keeping it in one language and one project is a real correctness advantage
- Small teams where eliminating the API boundary layer directly reduces headcount requirements
Where Blazor Cost Us
Blazor Server's dependency on a live SignalR connection is a real architectural constraint, not a minor footnote. Every active user maintains an open connection to the server. At small scale — a handful of school districts, hundreds of concurrent users — this is fine. At tens of thousands of concurrent users, your server memory and connection management become real infrastructure problems. We designed OpsFlow's infrastructure with this in mind, but a founder who picks Blazor Server for a high-concurrency consumer product without understanding this constraint will run into scaling pain that feels surprising.
The component ecosystem is also thinner than React's. When we needed specific UI behaviors, we sometimes had to build them ourselves or evaluate younger, less-battle-tested libraries. This cost is decreasing as the Blazor ecosystem matures, but in 2025 it's still a real consideration. If your product needs a highly customized data grid, a rich text editor with specific behavior, or complex drag-and-drop interactions, budget time to evaluate what's available before assuming you'll find a drop-in library.
Hiring is also a legitimate concern. The pool of developers who know Blazor well is smaller than the pool who know React. If you're building a team and planning to hire into it, React gives you more candidates. Blazor attracts strong .NET developers — that's a quality hire — but the supply is narrower. This matters more for some businesses than others, but it's not a reason to pretend it isn't true.
The .NET 8/9 Blazor Landscape Changes the Calculation
Any honest comparison in 2025 has to address Blazor United and the Auto render mode introduced in .NET 8 and refined in .NET 9. This isn't a minor update — it's a fundamentally different architectural option. Before .NET 8, you were choosing between Blazor Server (persistent connection, server-side execution) and Blazor WebAssembly (client-side execution, large initial download, limited server access). These were genuinely different models with genuinely different tradeoffs.
Blazor Auto changes this. A component can now start rendering via Server mode on first load — fast, no WASM download wait — and then seamlessly transition to WebAssembly after the runtime downloads in the background. You get the fast initial load of Server mode and the offline-capable, connection-independent execution of WebAssembly for subsequent interactions. You can also mix render modes at the component level within a single application, opting specific components into static SSR, interactive Server, or interactive WebAssembly based on their needs.
This closes a meaningful gap with Next.js-style React, which has been able to mix server and client rendering for years. For a founder evaluating Blazor and worrying that they're locked into the SignalR-connection scaling constraint of Server mode, Blazor Auto is a real answer. We are actively evaluating it for the next major OpsFlow architectural cycle. It's not production-battle-tested across the same breadth of use cases that Blazor Server is, but it's not experimental either — Microsoft is shipping it and it's the direction the platform is moving.
Our Actual Decision Framework
When a founder or operator comes to us with a new SaaS idea, we run through a set of concrete questions before we ever discuss framework preference. Here's how we actually think about this decision:
- What language is your backend? If the answer is C# and .NET, default to Blazor and require a specific reason to deviate. The monolith advantage — shared models, direct service calls, one deployment artifact — is worth protecting unless something concrete argues against it.
- Is the frontend team JavaScript-native with no .NET background? If yes, React is often the right call — not because React is better, but because forcing a team to learn a new paradigm mid-project is a delivery risk you can avoid.
- Does your application need to work offline or in low-connectivity environments? If yes, Blazor Server is not your answer. Evaluate Blazor WebAssembly, Blazor Auto, or React with service workers — this is a hard architectural requirement, not a preference.
- Are you building a consumer product with tens of thousands of concurrent users at launch? Blazor Server's per-user server connection cost will matter at that scale. Either design your infrastructure for it explicitly, or choose a render mode (WASM, Auto) that doesn't carry that constraint.
- Does the UI require highly interactive, fine-grained component composition that you'd need a specialized JS library to handle? Check the Blazor ecosystem first — it may exist. If it doesn't and building it yourself costs more than the other advantages are worth, React is a legitimate answer.
- What's your hiring plan for the next 12 months? If you're building a team and posting job reqs, React gives you more candidates. Factor this into your cost-of-talent projection honestly — it doesn't change the technical answer but it changes the business answer.
- What render mode does your application actually need in 2025? Don't default to Blazor Server for a new greenfield app without evaluating Blazor Auto. If the connection-model constraint has been holding you back from Blazor, revisit the decision with .NET 8/9 capabilities in hand.
The Answer We Actually Give Founders
If you're a .NET shop building a vertical SaaS for an enterprise or institutional buyer — K-12, healthcare, logistics, field services, wholesale distribution — and your team is C#-native, Blazor is very likely the right call. The productivity advantage of eliminating the API boundary is real. The security model is appropriate for enterprise buyers. The rendering flexibility in .NET 8/9 has addressed many of the historical objections. OpsFlow is evidence that it works in production at real scale with real institutional clients.
If you're building a consumer product, a mobile-first experience, a product with a design team that operates in JavaScript-native tooling, or a frontend that needs to integrate cleanly with an API owned by someone else — React is a serious option and we'll tell you so. The Petrey wholesale platform is evidence that we use React when it's the right tool. We don't have a framework loyalty that overrides engineering judgment.
What we've never recommended is picking a framework because of a blog post that didn't ship anything. The honest answer is that both are production-capable, both have real costs, and the decision turns on specifics that are unique to your product, your team, and your users. If you're working through that decision right now, we're happy to talk through the specifics of your situation — you can reach us at phaseable.com/contact.

Paul Evans
Founder & Engineer, Phaseable
I've been building software for 20+ years. I founded Phaseable to build industry-defining vertical SaaS products and help founders with niche problems turn them into real businesses.
Keep Reading
How OpsFlow Went From a Conversation to a Live SaaS in 4 School Districts
It started with a relationship, a real pain point, and a problem no existing software solved well. Here's the full origin story.
Read MoreVertical SaaSHow to Find a Vertical SaaS Opportunity Worth Building
The best vertical SaaS products come from insiders who've lived the problem. Here's a framework for identifying the gaps worth solving.
Read More