← Back to Article List         
ASP.NET Core Environment Settings

ASP.NET Core Environment Settings

Published on 26 Sep 2026     9 min read Web API
Web API

appsettings.json contains common settings. appsettings.{Environment}.json contains settings that override them for the active environment.

ASP.NET Core selects the environment-specific file automatically when you use:

var builder = WebApplication.CreateBuilder(args);

Use these exact filename conventions:

appsettings.json
appsettings.Development.json
appsettings.UAT.json
appsettings.Production.json

Use consistent casing. File paths can be case-sensitive on Linux, so appSettings.production.json may not match the expected filename.

1. What is each file used for?

File Purpose When loaded
appsettings.json Common settings and defaults Every environment
appsettings.Development.json Local development overrides Environment is Development
appsettings.UAT.json User Acceptance Testing overrides Environment is UAT
appsettings.Production.json Live application overrides Environment is Production

Development, Staging, and Production are conventional environment names. UAT is a valid custom environment name. Microsoft Learn

2. How does ASP.NET Core select the environment?

You normally set an environment variable on the machine, hosting platform, or application process:

ASPNETCORE_ENVIRONMENT=UAT

ASP.NET Core then loads:

appsettings.json
appsettings.UAT.json

For:

ASPNETCORE_ENVIRONMENT=Production

It loads:

appsettings.json
appsettings.Production.json

It does not load Development, UAT, and Production files together.

If no environment is configured, the default is Production.

For modern applications using WebApplication.CreateBuilder, DOTNET_ENVIRONMENT can also select the environment and takes precedence over ASPNETCORE_ENVIRONMENT if both are set. Avoid configuring conflicting values. Microsoft Learn

3. Simple configuration example

appsettings.json — common settings

{
  "ApplicationSettings": {
    "ApplicationName": "Product API",
    "SupportEmail": "support@example.com",
    "PageSize": 20
  },
  "ExternalApi": {
    "BaseUrl": "https://sandbox.example.com"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

These settings provide the baseline for all environments.

appsettings.Development.json

{
  "ApplicationSettings": {
    "PageSize": 5
  },
  "ExternalApi": {
    "BaseUrl": "https://localhost:7002"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Debug"
    }
  }
}

appsettings.UAT.json

{
  "ApplicationSettings": {
    "PageSize": 10
  },
  "ExternalApi": {
    "BaseUrl": "https://uat-api.example.com"
  }
}

appsettings.Production.json

{
  "ApplicationSettings": {
    "PageSize": 50
  },
  "ExternalApi": {
    "BaseUrl": "https://api.example.com"
  }
}

4. What values will the application actually use?

Assuming no other configuration source overrides these values:

Setting Development UAT Production
Application name Product API Product API Product API
Support email support@example.com support@example.com support@example.com
Page size 5 10 50
External API URL Local API UAT API Production API
Default log level Debug Information Information

Settings are overridden by key, not by replacing the entire file or section.

For example, Production only overrides:

"ApplicationSettings": {
  "PageSize": 50
}

The effective section still contains:

{
  "ApplicationName": "Product API",
  "SupportEmail": "support@example.com",
  "PageSize": 50
}

The name and email remain available from the common file. This follows the configuration rule that later providers override earlier values for matching keys. Microsoft Learn

5. Read the settings in your program

A simple Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

var applicationName =
    app.Configuration["ApplicationSettings:ApplicationName"];

var pageSize =
    app.Configuration.GetValue<int>("ApplicationSettings:PageSize");

var externalApiUrl =
    app.Configuration["ExternalApi:BaseUrl"];

app.Logger.LogInformation(
    "Environment: {Environment}, Application: {Application}, PageSize: {PageSize}",
    app.Environment.EnvironmentName,
    applicationName,
    pageSize);

app.MapControllers();

app.Run();

For UAT, the log includes:

Environment: UAT, Application: Product API, PageSize: 10

You do not need to manually read appsettings.UAT.json. Configuration exposes the combined effective values.

To read a connection string:

var connectionString =
    builder.Configuration.GetConnectionString("DefaultConnection");

This reads the effective value of:

ConnectionStrings:DefaultConnection

Avoid logging connection strings, passwords, or tokens.

6. How do we set the environment locally?

Option A: Visual Studio — launchSettings.json

This file is under the Properties folder.

You can define separate launch profiles:

{
  "profiles": {
    "Development": {
      "commandName": "Project",
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "UAT": {
      "commandName": "Project",
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "UAT"
      }
    }
  }
}

Select the required profile beside Visual Studio’s Run button.

Or run:

dotnet run --launch-profile UAT

This runs your local application using the UAT environment name. It does not deploy anything to a UAT server.

launchSettings.json is for local launch tooling; deployed applications do not use it to choose their environment. Microsoft Learn

Option B: PowerShell

$env:ASPNETCORE_ENVIRONMENT = "UAT"

dotnet run --no-launch-profile

For Production:

$env:ASPNETCORE_ENVIRONMENT = "Production"

dotnet run --no-launch-profile

--no-launch-profile prevents a local launch profile from supplying different settings.

7. How does this work after deployment?

The hosting environment supplies the environment name.

For example, configure these values in your Azure App Service application settings/environment variables:

Hosting application Setting Value
UAT application ASPNETCORE_ENVIRONMENT UAT
Production application ASPNETCORE_ENVIRONMENT Production

Each application loads its corresponding file when it starts.

You do not need code such as:

// Not required for normal environment selection.
if (serverName == "ProductionServer")
{
    // Load production configuration.
}

Publishing with Release does not select Production.

Concept Controls
Debug / Release Build configuration
Development / UAT / Production Runtime environment

For example:

dotnet publish -c Release

Creates a Release build that can run in either UAT or Production, depending on the runtime environment.

8. Which setting takes priority?

With the default WebApplication.CreateBuilder(args) configuration, these application sources have increasing priority:

Priority Source
1 — Lowest appsettings.json
2 appsettings.{Environment}.json
3 User Secrets in Development, when configured
4 Environment variables
5 — Highest Command-line arguments

A higher-priority source overrides the same key from a lower-priority source. Custom providers can change the final order. Microsoft Learn

For example:

appsettings.json:

{
  "ApplicationSettings": {
    "PageSize": 20
  }
}

appsettings.Production.json:

{
  "ApplicationSettings": {
    "PageSize": 50
  }
}

Hosting environment variable:

ApplicationSettings__PageSize=100

Final value: 100.

Use double underscores in environment variable names to represent nested configuration keys:

Environment variable Configuration key
ApplicationSettings__PageSize ApplicationSettings:PageSize
ConnectionStrings__DefaultConnection ConnectionStrings:DefaultConnection
JwtSettings__Secret JwtSettings:Secret

The double-underscore format works across platforms. Microsoft Learn

9. What is the common industry approach?

There is no single mandatory standard, but a widely used approach is:

A. Keep common, non-secret defaults in appsettings.json

Examples:

  • Default page size.
  • Application name.
  • General logging levels.
  • Non-sensitive timeout settings.

B. Keep environment files small

Only include values that differ between environments.

For example:

{
  "ExternalApi": {
    "BaseUrl": "https://uat-api.example.com"
  }
}

Avoid copying the entire base file into every environment file. Duplication makes configuration harder to maintain.

C. Keep secrets outside committed JSON files

Setting Typical storage
Local database password User Secrets
Production database password Secret manager or protected hosting configuration
JWT signing secret Secret manager
External service API key Secret manager
Non-secret service URL Environment JSON or hosting configuration

For Azure applications, Azure Key Vault with managed identity is a common approach.

An environment-specific filename does not make its contents secure.

D. Build once and promote the same artifact

A typical deployment process is:

  1. Build and test the application.
  2. Produce a Release artifact.
  3. Deploy that artifact to UAT.
  4. Supply UAT configuration and secrets.
  5. After approval, deploy the same artifact to Production.
  6. Supply Production configuration and secrets.

This reduces differences between the code tested in UAT and the code released to Production.

E. Keep environments isolated

UAT should have its own databases, credentials, storage, and external service configuration.

For example:

Environment Database External payment service
Development Local development database Sandbox
UAT UAT database Sandbox/test account
Production Production database Live account

Use separate identities and permissions so an incorrect setting cannot easily give UAT access to production resources.

F. Validate required settings at startup

Fail early if a required setting is missing:

var connectionString =
    builder.Configuration.GetConnectionString("DefaultConnection");

if (string.IsNullOrWhiteSpace(connectionString))
{
    throw new InvalidOperationException(
        "DefaultConnection is not configured.");
}

For larger applications, strongly typed options with startup validation make this more maintainable.

10. Common mistakes

Mistake Correct understanding
Creating appsettings.UAT.json automatically activates UAT The runtime environment must be set to UAT
Putting the environment name inside appsettings.json selects the file Environment selection happens during host initialization
Publishing in Release selects Production Build configuration and runtime environment are separate
launchSettings.json controls the deployed application It controls local launch profiles
Production settings replace the entire common file Matching keys override; other values remain
UAT automatically loads appsettings.Staging.json Only appsettings.UAT.json is selected
A missing environment file always stops startup Default environment JSON files are optional
Environment variables always override every provider A custom provider added later can override them

The optional-file behavior is especially important: a misspelled environment or missing file can leave your application using base defaults.

11. Key points

  • Use appsettings.json for common defaults.
  • Use appsettings.UAT.json and appsettings.Production.json for environment overrides.
  • WebApplication.CreateBuilder(args) loads them automatically.
  • Set the environment in the hosting platform or application process.
  • Use exact, consistent filename casing.
  • The default environment is Production when none is configured.
  • Restart the application when changing its runtime environment.
  • Keep secrets out of source-controlled settings files.
  • Prefer the same build artifact across UAT and Production.
  • Log the environment name at startup, but never log secrets.
  • Custom environments require explicit checks:
if (builder.Environment.IsEnvironment("UAT"))
{
    // UAT-specific behavior, only when necessary.
}
  • IsProduction() returns false in UAT. Any configuration code guarded only by IsProduction()—including loading a secret provider—will not run in UAT.

 

The last registered configuration provider wins when the same connection-string key exists in multiple sources.

For this common setup:

var builder = WebApplication.CreateBuilder(args);

// Added AFTER the default configuration providers.
builder.Configuration.AddAzureKeyVault(
    new Uri(builder.Configuration["KeyVault:VaultUri"]!),
    new DefaultAzureCredential());

Azure Key Vault wins, because you added it after the default providers, including environment variables.

Source Example value Priority in this setup
appsettings.json JSON database connection Lowest
Environment variable Environment database connection Higher
Azure Key Vault Key Vault database connection Highest — selected

ASP.NET Core uses provider registration order to resolve duplicate keys. Environment variables override JSON by default; a provider added afterward can override both. learn.microsoft.com

The names must represent the same configuration key:

Source Name
appsettings.json "ConnectionStrings": { "DefaultConnection": "..." }
Environment variable ConnectionStrings__DefaultConnection
Azure Key Vault secret ConnectionStrings--DefaultConnection
Key used by .NET ConnectionStrings:DefaultConnection

Your application reads the final value using:

var connectionString =
    builder.Configuration.GetConnectionString("DefaultConnection");

What happens in different situations?

Situation Selected value
Key Vault added last and contains the key Key Vault
Key Vault loads successfully but does not contain that key Environment variable
Neither Key Vault nor environment variables contains it JSON configuration
Key Vault cannot be accessed during loading Normally a startup error, not automatic fallback

If your Key Vault registration is inside:

if (builder.Environment.IsProduction())
{
    builder.Configuration.AddAzureKeyVault(
        new Uri(builder.Configuration["KeyVault:VaultUri"]!),
        new DefaultAzureCredential());
}

Then Key Vault participates only in Production. In UAT or Development, the environment variable overrides appsettings.json.

Key point: Key Vault has no permanent built-in “highest priority.” It wins here because you registered it last.