In-Process vs Out-of-Process in ASP.NET Core – What, Why, When?


When deploying ASP.NET Core applications, developers often face confusion around hosting models—specifically, the difference between In-Process and Out-of-Process hosting. These models determine how your app interacts with the web server, and choosing the right one can significantly affect your app's performance and architecture.
In this post, we'll walk through:
Why hosting model matters
IIS, Kestrel, and their roles
What is In-Process hosting?
What is Out-of-Process hosting?
The role of aspNetCoreModule and aspNetCoreModuleV2
A practical comparison: pros, cons, and when to use what
Real-world Visual Studio behavior and deployment observations
Why Does the Hosting Model Matter?
The hosting model defines how your ASP.NET Core application handles incoming HTTP requests:
Does IIS directly execute your app?
Or does IIS act as a reverse proxy to another internal server (Kestrel)?
These decisions impact:
Performance
Request processing pipeline
Deployment strategy
Debugging and logging behavior
Understanding these models gives you control over your application's behavior in production.
A Quick Note on IIS, Kestrel, and ASP.NET Core
Kestrel is the cross-platform web server built into ASP.NET Core. It can run standalone.
IIS is a full-featured Windows web server.
ASP.NET Core is not tied to IIS like the old .NET Framework. It's flexible. You can host your app on Linux using Nginx, on Windows using IIS, or even run it directly via Kestrel.
What is In-Process Hosting?
In In-Process hosting, your ASP.NET Core app runs inside the IIS worker process (w3wp.exe). The IIS process loads your app directly, and your app uses the IIS HTTP pipeline to handle requests.
There is no Kestrel involved in serving HTTP. This results in lower overhead and faster request handling.
How it works:
Key Traits of In-Process:
Fastest performance (no reverse proxy)
No Kestrel server needed
Only available on Windows
Requires
aspNetCoreModuleV2
in IIS
Example Web.config Snippet:
<aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
What is Out-of-Process Hosting?
In Out-of-Process hosting, your app runs in a separate process from IIS. This process hosts Kestrel, which listens for HTTP requests. IIS acts as a reverse proxy that forwards external requests to Kestrel.
How it works:
Key Traits of Out-of-Process:
Works cross-platform (Windows/Linux)
Requires Kestrel to run the app
Slightly slower due to reverse proxying
More configurable
Supports both
aspNetCoreModule
(legacy) andaspNetCoreModuleV2
Example Web.config Snippet:
<aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="OutOfProcess" />
Real-World Observations (Visual Studio Experience)
When you're working with an ASP.NET Core app in Visual Studio, your experience depends on what you select in the run/debug dropdown:
When You Select Project
(with HTTP or HTTPS):
A console window opens.
The app runs via Kestrel.
You see Swagger UI in the browser.
This means it's running in Out-of-Process, even if your project is configured as
InProcess
.
When You Select IIS Express
:
No console window opens.
The browser opens directly.
The app is running via IIS Express, which uses In-Process hosting if enabled.
Important Note:
Even if your project is configured with InProcess
in csproj, it will behave like Out-of-Process in the console scenario because Visual Studio bypasses IIS for that mode.
Changing the Hosting Model in .NET 8 Projects (Visual Studio + Deployment Package)
In .NET 8, the hosting model isn't explicitly shown in the Visual Studio GUI unless you're editing an IIS Express profile (via the launch settings UI). But this doesn't control your production deployment behavior directly.
Locally, your app usually runs based on what's defined in launchSettings.json
— you might choose to run it via:
IIS Express (typically In-Process by default)
HTTPS (Kestrel)
HTTP (Kestrel)
But for deployment, what really matters is the setting in your .csproj
file.
Step 1: Edit Your .csproj
File
To change the hosting model, explicitly add the following inside your main <PropertyGroup>
:
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
By default, it's InProcess
, so you only need to specify this if you're switching to Out-of-Process.
Step 2: Publish the Application
When you publish the app (e.g., using dotnet publish
or Visual Studio's Publish UI), .NET generates a web.config
file only in the output publish directory, not in the source code.
That web.config
will now include:
<aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="OutOfProcess" />
This web.config
is what IIS uses during deployment to determine how your app should be hosted.
Note: In .NET Core 3.1 and later (including .NET 8), this
web.config
is generated at publish time — it's not part of your project by default.
Target Runtime Options When Publishing
When creating a deployment package, you’re asked to choose a Target Runtime:
These options control how and where your app can run:
Runtime | Description |
portable | Default. Requires .NET runtime to be installed on the host system. |
win-x86 , win-x64 | For Windows machines. Self-contained if you include the runtime. |
win-arm , win-arm64 | For ARM-based Windows devices (e.g., Surface Pro X). |
linux-x64 , linux-arm , linux-arm64 | For Linux deployments (e.g., Ubuntu, Raspberry Pi). |
osx-x64 , osx-arm64 | For macOS Intel and Apple Silicon systems. |
Tip: If you select a specific runtime (e.g.,
win-x64
) and enable self-contained deployment, the entire .NET runtime is bundled. This increases package size but removes dependency on the server having .NET installed.
What Are These Modules?
aspNetCoreModule (ANCM v1):
Used in .NET Core 2.x apps
Only supports Out-of-Process hosting
aspNetCoreModuleV2 (ANCM v2):
Introduced in .NET Core 2.2+
Supports both In-Process and Out-of-Process hosting
Used by default in ASP.NET Core 3.1 and later
If you're using In-Process hosting but have the old
aspNetCoreModule
, your app won't run. That module simply doesn't support In-Process mode.
In-Process vs Out-of-Process: Comparison
Feature | In-Process | Out-of-Process |
Kestrel used | No | Yes |
IIS role | Runs app directly | Acts as proxy |
Performance | Faster | Slightly slower |
Cross-platform | No (Windows only) | Yes |
Supported module | V2 only | V1 / V2 |
Flexibility / Custom config | Less | More |
When to Use What?
Use In-Process if:
You are deploying to IIS on Windows
You want the best possible performance
You don’t need Kestrel-specific config (e.g., Listen on custom ports)
Use Out-of-Process if:
You need cross-platform hosting (e.g., Linux + Nginx)
You are hosting multiple apps with complex routing
You want custom Kestrel behavior (HTTPS setup, ports, etc.)
FAQs Developers Often Have
Does Kestrel always run with ASP.NET Core?
No. Kestrel only runs in Out-of-Process hosting.
If I deploy on Windows Server, do I have to use IIS?
No. You can run your app as a standalone process and expose Kestrel on a public port, or use something like Nginx as reverse proxy.
Can multiple apps share the same IIS process?
No. Each IIS App Pool gets its own w3wp.exe process.
Is In-Process always better?
Performance-wise, yes. But Out-of-Process gives you more flexibility and works cross-platform.
Final Thoughts
Choosing between In-Process and Out-of-Process isn't just a deployment checkbox. It's a design choice that affects your app's performance, portability, and infrastructure. For high-performance production apps on Windows, In-Process is ideal. For custom setups, containers, or Linux hosting, Out-of-Process offers more control.
Subscribe to my newsletter
Read articles from Waleed Naveed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
