In previous article, you already know Blazor Server and Blazor WebAssembly share many similarities but also have significant differences. Of course, Blazor Server runs on the server, and Blazor WebAssembly runs on WebAssembly in the browser. However, 5 key differences below will go further than that and are more hands-on.
Project Structure (1 vs. 3)
The project structure is the first difference between Blazor Server and Blazor WebAssembly. As you can see in Todo list app with Blazor Server on the left and Blazor WebAssembly on the right.

We have a single project in the Blazor Server application. It contains the Blazor components, the services accessing the data, and all data objects.
In the Blazor WebAssembly application, we have three projects. The Client project contains the Blazor components. The Server project contains the services and an API layer to make the services available to the client over an HTTP connection. The Shared project contains data objects that are used in both the Client and the Server projects. The project structure of a Blazor Server application is a lot simpler. You can access all the resources within a single project because all the code runs on the server.
No-Api vs. API
A Blazor Server project does not have an API layer.
However, for Blazor WebAssembly, you must implement an API. Even if the web application is the only API consumer, you still have to implement it. For example, to keep secrets such as DB connection strings on the server. If you have a Blazor Server application, you can still share code. Nobody prevents you from sharing code using a class library. You can, for example, extract one or more services into a class library and use it in different Blazor Server applications. You can, but you don’t need to have multiple projects.
Simplicity vs. Scalability
A Blazor WebAssembly application downloads to the client and executes client-side. It only connects to the server when fetching or sending data over HTTP. It puts less pressure on the server, which makes it simpler to scale. Besides running on a bigger server, you can also scale out and have multiple API servers behind a load balancer. A Blazor WebAssembly application can be served from any web server.
For a Blazor Server application, we have a persistent web socket connection using SignalR between the client and the server. The server must be running an ASP.NET Core application. However, since no WebAssembly is involved, a Blazor Server application runs on all browsers and devices because it only uses HTML, CSS, and JavaScript on the client.
Scaling a Blazor Server application is simple when you add more resources to the same server. However, scaling out (adding more servers) will be a bigger challenge since all clients must always be connected to the same server. We can also say that Blazor WebAssembly applications run stateless while Blazor Server applications are stateful. The server manages the state for all connected clients.
Same Objects vs. Different Objects in Services
As you can see in example, we render all todo items in the Index component. We also have a button that the user can click to delete a todo item. In the Blazor Server application, we inject the TodoService and provide the instance of the TodoItem. In the TodoService, we can use the object to find it and remove it from the collection.

In the Blazor WebAssembly application, we call an API to delete the todo item and provide an id or, in this case, the text of the todo item.

On the server, we call the TodoService in the TodoController and provide the text. In the TodoService, we need to find the correct todo item from the collection by its id or text.

TodoService.cs:

When using Blazor Server, we have all the data and context that we need. When using Blazor WebAssembly, we usually must reload data from the database for every stateless call. Of course, you can use caching, but that introduces another level of complexity.
First Load Performance
When using Blazor Server, the application loads very fast. It only has to download the Blazor JavaScript bundle and render the first page. The size of the initial download remains the same, no matter how big your application grows.
When using Blazor WebAssembly, the whole application will be downloaded on the initial load. Depending on the size of the application, it can take a few seconds to load. Also, the size of the application grows over time when more and more features are added.
Conclusion
You have a good understanding of how many users the application will have simultaneously. The programming model is simpler. It’s less code, and the code is simpler as well. You have less data reloading and no forced API layer. If you want to build a public-facing application that will be used by thousands or tens of thousands of users simultaneously, Blazor Server might hit its limits. You will run into scaling issues that are simpler to solve using Blazor WebAssembly.
Also, suppose your application doesn’t need to call the server for every operation, for example, because a lot of logic can be included in the application. In that case, you have less network traffic, making it work better in case of bad network connection or offline scenarios. The best thing about working with Blazor is that both hosting models share many similarities making it easy to learn developing for both models. Also, you can migrate an application from Blazor Server to Blazor WebAssembly or the other way with a reasonable effort.