In ASP.NET Core, configuration settings are usually loaded at startup (for example from appsettings.json, environment variables, or other configuration sources). When you change configuration values at runtime (e.g. modifying the appsettings.json file or updating a dynamic store), the application typically must be restarted for changes to take full effect.
In many hosting environments, you don’t have direct manual control (for example, in containerized setups or automated deployments). It can be useful to implement an automatic or programmatic restart mechanism, so that your app picks up configuration changes immediately without manual intervention.
In this article, we’ll explore common approaches, trade-offs, and sample code to automatically restart an ASP.NET Core application after modifying configuration in code.
Why appsettings changes typically require restart
By default, configuration in ASP.NET Core is loaded early during host building. If you use the IOptions<T> pattern, your settings are typically bound once and stored in memory. Subsequent changes to configuration files or sources won’t necessarily propagate automatically.
Even though the default CreateDefaultBuilder() wiring configures JSON files with reloadOnChange = true, merely enabling file change detection doesn’t guarantee that all parts of your app will respond automatically — it depends on how configuration is consumed (via IOptions, IOptionsSnapshot, IOptionsMonitor, direct IConfiguration, etc.).
Many settings (e.g. DI-bound singletons or stateful services) may not refresh properly unless the process is restarted. Also, some frameworks or libraries expect configuration to be static at startup.
Therefore, an automatic restart may sometimes be the most straightforward path to consistent behavior after a configuration change.
Approaches to automatic restart
Here are various strategies to trigger or perform a restart of an ASP.NET Core app when configuration changes.
1. Use IHostApplicationLifetime.StopApplication() (graceful shutdown)
You can use the IHostApplicationLifetime (or in newer hosts, IHostApplicationLifetime, or via IHost.StopAsync) to request a graceful shutdown of the application. In many hosting environments (e.g. when hosted behind IIS or in containers), the process manager or the hosting infrastructure will re-launch the application.
Sample code (in .NET 6+ minimal hosting):
// In Program.cs or wherever you have access to IHost
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// register configuration watchers, etc.
services.AddSingleton<ConfigurationWatcher>();
})
.Build();
var watcher = host.Services.GetRequiredService<ConfigurationWatcher>();
watcher.StartWatching();
// run host
await host.RunAsync();
// ConfigurationWatcher
public class ConfigurationWatcher
{
private readonly IHostApplicationLifetime _lifetime;
private readonly IConfiguration _configuration;
public ConfigurationWatcher(IHostApplicationLifetime lifetime, IConfiguration configuration)
{
_lifetime = lifetime;
_configuration = configuration;
}
public void StartWatching()
{
// Example: register change listener or monitor file changes
ChangeToken.OnChange(
() => _configuration.GetReloadToken(),
() => OnConfigurationChanged());
}
private void OnConfigurationChanged()
{
// perform any validation or logic first...
// then stop the application
_lifetime.StopApplication();
}
}
When StopApplication() is called, the host begins a graceful shutdown. If your environment is configured so that the application is restarted (for example, IIS recycles, or a container orchestrator restarts it), then the new instance will start with fresh settings.
Notes / caveats:
- This method depends on the hosting environment to restart the app. If the host isn't set up to restart (for example a simple console run without supervision), then the app will just stop.
- You should ensure there is a short downtime or design for transient unavailability during the restart.
- Consider introducing delays, backoff, or limiting how often you restart to avoid loops or thrashing.
2. Touch or modify a “watched file” to trigger host recycling (IIS / Kestrel interplay)
In IIS-hosted ASP.NET Core applications, you may trick the underlying application infrastructure into recycling the process by touching a file that IIS or the ASP.NET Core Module monitors (for example, web.config). Sometimes updating web.config can force the application to be reloaded in IIS context.
For example, you might programmatically write a no-op change (e.g. increment a timestamp comment) to web.config. This may cause IIS / the ASP.NET Core Module to detect a config change and recycle the application.
However, this approach is brittle:
- It depends on the hosting being under IIS + ANCM.
- It may not reliably trigger in all hosting modes.
- It’s somewhat of a hack and might lead to unexpected side effects.
3. Use external supervisory process / monitoring
Instead of embedding restart logic within the app, another approach is to externalize the detection and restart responsibility:
- Use a file watcher or configuration change monitor in a separate process or script (PowerShell, Bash, watchdog, etc.).
- When a change is detected, issue a command to recycle the application pool (IIS), restart the Windows service, send a kill/stop to the process and let the host restart, or otherwise invoke your deployment automation to restart the app.
- In containerized or orchestration contexts (e.g. Kubernetes, Docker, systemd), you can configure the process manager to detect exit and relaunch automatically.
This external approach can be more robust and decoupled from your application code.
4. Hybrid: In-app notification + external webhook to orchestrator
You can combine approaches. For example:
- The application detects the config change internally.
- The app sends a webhook or message to an orchestration service (e.g. Azure DevOps, Kubernetes API, a service bus).
- That service then triggers a restart (for instance, by calling a management API, restarting a container, or restarting a VM).
This is useful in environments where your app code doesn’t have permission to restart itself, but an external control plane does.
Example end-to-end code sketch
Here’s a more fleshed-out example using minimal hosting in .NET 6+:
using Microsoft.Extensions.Primitives;
var builder = WebApplication.CreateBuilder(args);
// add config watching or custom handling
builder.Services.AddSingleton<ConfigurationRestarter>();
var app = builder.Build();
// kick off watching after app is built
var restarter = app.Services.GetRequiredService<ConfigurationRestarter>();
restarter.Start(app);
app.MapGet("/", () => "Hello world");
await app.RunAsync();
public class ConfigurationRestarter
{
private readonly IConfiguration _config;
private readonly ILogger<ConfigurationRestarter> _logger;
public ConfigurationRestarter(IConfiguration config, ILogger<ConfigurationRestarter> logger)
{
_config = config;
_logger = logger;
}
public void Start(WebApplication app)
{
ChangeToken.OnChange(
() => _config.GetReloadToken(),
() => OnChange(app));
}
private void OnChange(WebApplication app)
{
_logger.LogInformation("Configuration changed, scheduling app shutdown.");
// optional: add delay or debounce to avoid frequent restarts
Task.Delay(TimeSpan.FromSeconds(2)).ContinueWith(_ =>
{
app.Lifetime.StopApplication();
});
}
}
In this setup:
- We listen for configuration change tokens via GetReloadToken() (works when configuration providers support reload).
- After detecting a change, we schedule a small delay and then call StopApplication().
- The host will wind down gracefully. If the environment restarts the app, the new run will load the new configuration.
You can enhance this with:
- Validation logic before restart.
- Restart cooldowns or rate-limiting.
- Notifications/logging of restarts.
- Fallbacks if restart fails.
Hosting considerations & fallback strategies
When implementing an automatic restart, you must consider how your application is hosted. Some environments won’t automatically bring your app back after calling StopApplication(). Below are a few common hosting scenarios and how to handle them.
IIS / ASP.NET Core Module (ANCM)
- IIS uses the ASP.NET Core Module (ANCM) to manage the process. If the process exits or is shut down, IIS can relaunch it on the next HTTP request.
- You can configure the app pool to AlwaysRunning and enable preload to reduce cold start latency.
- In some cases, modifying web.config triggers an application recycle.
- Be careful: if you force stop the app too quickly, there may be ongoing requests or startup race conditions.
Windows Service / Windows Host
- If you host your ASP.NET Core application as a Windows Service, you should set the service recovery options to restart the service on failure.
- When your process exits (e.g. via StopApplication()), the Windows Service manager can detect this and automatically restart it.
Linux / systemd
- On Linux, you often run ASP.NET Core with a systemd unit file.
- You can configure Restart=always (or on-failure) in the .service file so that systemd automatically restarts the app if it stops.
- Calling StopApplication() will cause systemd to restart it.
Example myapp.service snippet:
[Service]
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/dotnet /var/www/myapp/MyApp.dll
Restart=always
RestartSec=5
Container environments / Orchestration (Kubernetes, Docker)
- In container contexts, exiting the process (via StopApplication()) typically causes the container to stop. The orchestrator (Docker, Kubernetes) will then restart it, assuming the pod or container spec is set for restart.
- Use liveness/readiness probes and restart policies (e.g. restartPolicy: Always) to ensure the container is relaunched.
- Because containers are ephemeral, this method fits neatly with infrastructure-driven restarts.
Alternatives: dynamic configuration without full restart
Sometimes a full restart is overkill. Depending on your use case, you might avoid restarts altogether by:
- Using IOptionsMonitor<T> to allow configuration to update at runtime.
- Reloading configuration providers (e.g. file watchers, database-backed providers).
- Implementing your own dynamic configuration service (e.g. refresh cache of settings from a database on a timer or on demand).
- Designing your services to respond to configuration change events (e.g. notifying dependent services to reload state) rather than relying on a full app restart.
However, for certain changes (e.g. altering DI registrations, injecting new middleware, or reconfiguring deeply baked infrastructure), restart may still be the safest approach.
Best practices & tips
- Debounce restarts: avoid rapid repeated restarts when multiple config changes occur in quick succession.
- Validate configuration before restarting to avoid restarting into a broken state.
- Log restarts, and send alerts so you know when the app is being recycled.
- Graceful shutdown: allow existing requests to complete, close connections, and cleanup resources.
- Use versioning, feature flags, or safe fallback defaults to prevent full disruption.
- In production, test this mechanism thoroughly in staging environments to avoid downtime surprises.
Conclusion
Automatically restarting your ASP.NET Core application after modifying settings can simplify configuration management in many scenarios. The most direct in-app method is using IHostApplicationLifetime.StopApplication() in response to configuration change detection, combined with hosting setup that will bring the app back up.
However, your approach should be tailored to your hosting environment (IIS, Windows Service, Linux/systemd, container, etc.), and you should always design for resilience, debouncing, and safe fallbacks.