Merging appsettings with environment variables in .NET Core
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In .NET, configuration is usually not a manual merge that you write yourself. Instead, you add configuration providers in order, and later providers override earlier ones. That is why appsettings.json plus environment variables works well: JSON provides the baseline, and environment variables can replace selected values at runtime.
Configuration Providers Are Layered in Order
The important rule is simple:
- add
appsettings.jsonfirst - add environment variables later
- later providers win when keys overlap
A minimal example with ConfigurationBuilder looks like this:
If the same key exists in both sources, the environment variable value overrides the JSON value.
Map Nested JSON Keys With Double Underscores
Nested configuration keys in .NET use : as the logical separator, but environment variables usually represent that separator with double underscores.
For example, this JSON:
can be overridden with an environment variable named:
That tells the configuration system to replace:
ConnectionStrings:DefaultConnection
with the environment-provided value.
A Practical Example
Suppose appsettings.json contains:
Then an environment variable such as:
overrides the JSON value at runtime without modifying the file. This is especially useful in containers, CI pipelines, and cloud deployments where the same application artifact runs in several environments.
Why This Pattern Is Useful
Using JSON plus environment variables gives you a clean separation:
- files hold default configuration
- environment variables hold environment-specific overrides
- secrets can be injected without hardcoding them into source control
That means one build artifact can move from development to staging to production without changing the code or rewriting the base settings file.
Prefer the Built-In Host Configuration
In modern ASP.NET Core apps, you often do not need to build this manually because the default host builder already includes JSON files and environment variables in the configuration pipeline. But it is still important to understand the merge order, especially when debugging why one value is winning over another.
If a setting seems wrong at runtime, the first question should be:
- which providers were added
- in what order
- which provider supplied the final value
That is usually the real answer behind "merging" behavior.
It also explains why the same application can behave differently across environments even when the JSON file is identical: the active environment may be providing different overrides through host configuration.
That is especially common in containers and cloud platforms, where deployment manifests or hosting dashboards inject environment variables outside the repository and outside the published application files.
Many applications also insert environment-specific JSON files such as appsettings.Production.json between the base JSON file and environment variables. The same ordering rule still applies: providers added later override earlier values, so environment variables remain a final override layer.
Common Pitfalls
- Thinking configuration sources are combined symmetrically rather than overridden in provider order.
- Using single underscores instead of double underscores for nested environment-variable keys.
- Forgetting that the environment variable must match the full configuration path exactly.
- Assuming the JSON file is wrong when an environment variable is silently overriding it.
- Storing secrets in
appsettings.jsoneven though the environment is supposed to provide them.
Summary
- In .NET, configuration merging is provider layering, not hand-written merge logic.
- Add
appsettings.jsonfirst and environment variables later so environment values override defaults. - Use double underscores in environment variable names to represent nested configuration keys.
- This pattern is ideal for environment-specific overrides and secret injection.
- When a value looks wrong, check provider order before changing the JSON file.

