In a previous post we talked about setting up IIS to host a .NET Core web app, and since then, I’ve had plenty of questions regarding why does ASP.NET Core even have the Kestrel Web Server (The inbuilt web server of the .NET Core platform), if you just host it in IIS anyway? Especially now that .NET Core can now run InProcess with IIS, it’s almost like having Kestrel is redundant. In some ways that may be true and for *most* use cases, you will want to use IIS. But here’s my quick rundown of why that might be (or might not be) the case.
Kestrel Features (Or Lack Thereof)
Now Kestrel is pretty featured, but it’s actually lacking a few fundamentals that may make it a bit of a blocker. Some of which are (but not limited to) :
- HTTP access logs aren’t collected in Kestrel. For some, this doesn’t matter. But for others that use these logs as a debugging tool (Or pump them to something like Azure Diagnostics etc), this could be an issue.
- Multiple apps on the same port is not supported in Kestrel simply by design. So when hosting on IIS, IIS itself listens on port 80 and “binds” websites to specific URLs. Kestrel on the other hand binds to an IP (Still with a website URL if you like), but you can’t then start another .NET Core Kestrel instance on the same port. It’s a one to one mapping.
- Windows Authentication does not exist on Kestrel as it’s cross platform (more on that later).
- IIS has a direct FTP integration setup if you deploy via this method (Kestrel does not)
- Request Filtering (e.g. Blocking access to certain file extensions, folders, verbs etc) is much more fully featured in IIS (Although some of this can be “coded” in Kestrel in some cases).
- Mime Type Mapping (e.g. A particular file extension being mapped to a particular mime type on response) is much better in IIS.
I would note that many feature comparisons floating around out there are very very dated. Things like request limits (e.g. Max file upload size/POST body size) and SSL certificates have been implemented in Kestrel for a few years now. Even the above list may slowly shrink over time, but for now, just know there there are certainly things inside Kestrel that you may be used to inside IIS.
Obviously .NET Core and by extension, Kestrel, is cross platform. That means it runs on Windows, Linux and Mac. IIS on the other hand is Windows only and probably forever will be. For those not on Windows systems, the choice of even using IIS is a non existent one. In these cases, you are comparing Kestrel to things like NGINX which can act as a reverse proxy and forward requests to Kestrel.
In some of these cases, especially if you don’t have experience using NGINX or Apache, then Kestrel is super easy to run on Linux (e.g. Double click your published app).
Just quickly anecdotally, the management of IIS is much easier than managing a range of Kestrel web services. Kestrel itself can be run from the command line, but therein lies the issue where you often have to set up your application as a Windows Service (More info here : Hosting An ASP.NET Core Web App As A Windows Service In .NET Core 3) so that it will automatically start on server restarts etc. You end up with all these individual “Windows Services” that you have to install/manage separately. On top of that, everything being code based can be both a boon for source control and IAC, but it can also be a headache to configure features across a range of applications. If you are used to setting things up in IIS and think that it’s a good experience, then you are better at sticking with it.
Existing Setup Matters
Your existing setup may affect your decision to use Kestrel vs IIS in two very distinct ways.
If you are already using IIS, and you want to keep it that way and manage everything through one portal, then you are going to pick IIS no matter what. And it makes sense, keeping things simple is almost always the right route. And IIS has great support for hosting .NET Core web apps (Just check our guide out here : Hosting An ASP.NET Core Web Application In IIS).
But conversely, you may have IIS installed already, but it isn’t set up to host .NET Core apps and you don’t want to (or can’t) install anything on the machine. In these cases, Kestrel is great for sitting side by side with your existing web server and it running completely in isolation. It can run listening to a non standard port, leaving your entire IIS setup intact. This also goes for hosting on a machine that doesn’t currently have IIS installed, Kestrel can be stood up immediately from code with little to no configuration without modifying the machine’s features or running an installer of any kind. It’s basically completely portable.
You’ll often find articles mentioning that Microsoft recommends using a reverse proxy, whether that be IIS, NGINX or Apache, to sit infront of Kestrel and be your public facing web server/proxy. Anecdotally, I’ve found this to be mentioned less and less as Kestrel gains more features. You will actually struggle to find mention of *not* using Kestrel on public facing websites in the official documentation nowadays (For .NET Core 3+). That’s not to say that it’s a good idea to use Kestrel for everything, just that it’s less of a security risk to these days.
My Final Take
Personally, I use both.
I use IIS as my defacto choice as 9 times out of 10, when working in an Windows environment, there is already a web server setup hosting .NET Framework apps. It just makes things easier to setup and manage, especially for developers that are new to .NET Core, they don’t have another paradigm to learn.
I use Kestrel generally when hosting smaller API’s that either don’t have IIS setup, don’t need IIS setup (e.g. a web app that just gets run on the local machine for local use), or have IIS setup but they don’t want to install the hosting bundle. Personally, I generally don’t end up using many IIS features like Windows Auth or FTP, so I don’t miss these features.