Hosting: Windows Service vs IIS
Erde installs in one of two hosting shapes: a Windows Service or behind IIS (Internet Information Services). You pick the shape at install time on the MSI's Deployment Configuration screen. This page explains how each shape works and which one to choose. Both run the same server binary — the difference is only what sits in front of it.
Both shapes run the same server
In both shapes, the Kestrel web server serves the full application. Kestrel handles the API routes (/api/*), the Blazor WebAssembly client (static files from the sibling client\wwwroot\ directory), and the single-page-application fallback (index.html for client-side routing). The only thing that changes between shapes is what process hosts Kestrel and what sits in front of it. Both shapes serve on the same HTTP port (default 5000) and against the same database.
The Server project wires Windows-Service hosting in unconditionally — Program.cs always calls UseWindowsService() with service name Erde. IIS hosting is configured separately at install time when you choose IIS mode; the same binary then runs in-process inside the IIS worker process.
Figure: In both shapes Kestrel serves the API and the client; IIS only adds a worker process in front of it.
How the two shapes compare
| Aspect | Windows Service | IIS |
|---|---|---|
| Best for | Small firm (1–5 users), single office | Multi-office, field crews, 5+ users |
| Process | Erde.Server.exe (standalone) | w3wp.exe (IIS worker process) |
| How Kestrel runs | Directly, via UseWindowsService() | In-process, via ASP.NET Core Module v2 (ANCM) |
| Port binding | --urls http://0.0.0.0:{port} | IIS site binding on {port} |
| Process management | Windows Service Control Manager (auto-restart on failure) | IIS app pool (health monitoring, crash restart) |
| Environment variable | Registry key under the service | <environmentVariable> in web.config |
| Static files | Kestrel UseStaticFiles middleware | Same — Kestrel middleware, not IIS |
| Network | LAN or VPN only | LAN, VPN, or internet-facing |
| SSL / HTTPS | Requires a reverse proxy (Caddy, etc.) | IIS Manager built-in certificate UI |
| Prerequisites | None beyond the .NET runtime | IIS enabled before install |
| Complexity | Low — runs as a background service | Moderate — IIS must be enabled first |
In IIS mode, the IIS site points directly at the api\ folder. ANCM loads the .NET runtime in-process within w3wp.exe and hands all requests to Kestrel. There is no separate client site and no virtual directory or application for the client — the client\ folder is never an IIS application. The API's web.config sets <httpErrors existingResponse="PassThrough" /> so ASP.NET Core error responses (such as 451 license errors) reach the browser unchanged, sets ASPNETCORE_ENVIRONMENT to Production, and uses hostingModel="inprocess". This in-process IIS hosting shape is distinct from putting a separate IIS or proxy in front of the Windows Service shape (out-of-process); for that case, see Put Erde behind a reverse proxy for HTTPS.
In Windows Service mode, the MSI installs a service named Erde (display name Erde Environmental Data Management) running as LocalSystem with start type Automatic. Its recovery policy restarts the service after 3 seconds on all failures, and it starts with the arguments --urls http://0.0.0.0:{port}. The ASPNETCORE_ENVIRONMENT=Production value is set through a registry key under the service instead of a web.config.
When to choose each
Choose Windows Service for a small firm — roughly 1–5 users in a single office on a LAN or VPN. It needs nothing beyond the .NET 10 Hosting Bundle and runs as a background service that the Windows Service Control Manager keeps alive. If you need HTTPS in this shape, put a reverse proxy (such as Caddy) in front of Erde.
Choose IIS for multi-office work, field crews, or 5 or more users, including internet-facing deployments. IIS gives you the app pool's health monitoring and crash restart and lets you manage TLS certificates from IIS Manager's built-in UI. IIS must be enabled before you install the .NET 10 Hosting Bundle; if it was enabled afterward, run a repair install of the Hosting Bundle so ANCM registers with IIS.
The installer configures the Erde app pool to run continuously: idle timeout and periodic recycling are disabled, the pool's start mode is AlwaysRunning, and the application is preloaded. IIS's defaults (a 20-minute idle stop and a 29-hour recycle) would silently stop the in-memory background import queue, so leave these settings as installed.
The start-mode and preload settings are applied by a best-effort installer step that is not rolled back if it fails. After an IIS install, confirm them — and re-apply if either is wrong:
& "$env:windir\System32\inetsrv\appcmd.exe" list apppool "Erde" /text:startMode # expect: AlwaysRunning
& "$env:windir\System32\inetsrv\appcmd.exe" list app "Erde/" /text:preloadEnabled # expect: true
The hosting shape is set per install, not stored in the database. To switch shapes, uninstall Erde and reinstall, picking the other option on the Deployment Configuration screen.
After the MSI finishes, the server still needs first-run configuration. On first start, with no appsettings.Production.json present, it boots into setup mode and serves the wizard at /setup regardless of which hosting shape you chose. See First-run setup.
Run a single worker process
Whichever shape you choose, run Erde as exactly one worker process: one Windows Service instance, or one IIS worker process. In IIS, leave the application pool's Maximum Worker Processes at 1 — do not enable a web garden — and do not load-balance several Erde nodes against the same database.
Erde keeps caches in process memory, including the per-user authorization access maps that back Site- and Project-level permissions. When an administrator changes a user's roles or access, the process that handled the change drops that user's cached map immediately — but a second worker process has its own cache and keeps serving the old permissions until its copy expires, up to five minutes later.