Changing a deployment environment value does not necessarily change a running FastAPI process. Configuration can be captured during build, import, startup or a cached settings call. Identify the read boundary, update the intended deployment revision and restart or deliberately reload only the configuration designed for that behavior. Treat dynamic runtime settings as a separate contract rather than assuming environment variables form a live shared store.
Follow the value from deployment to consumer
Choose one harmless feature setting and trace where it enters the process, where a settings object is created and which callers retain references. A module-level constant and a cached settings dependency can both preserve an old value, but at different times. Multiple worker processes also have independent memory. Clearing one process's cache does not update every worker or every instance in an autoscaled service.
FastAPI's settings guide demonstrates a cached settings dependency with lru_cache. The cache avoids constructing settings repeatedly; it also establishes a lifetime that tests and deployments must understand. Pydantic settings source precedence, environment files and validation can add other boundaries. Inspect the installed versions and selected sources before concluding which input actually won.
FastAPI: settings, environment variables and cached dependencies
A harmless executed cache experiment
Our isolated standard-library fixture uses APTIX_FIXTURE_FEATURE, a synthetic non-secret value. The first cached read sees off. The fixture changes that process's environment mapping to on, but the next cached read still sees off. After explicitly clearing the fixture cache, a new read sees on. This tests lru_cache behavior only; it does not modify a deployed service or validate Pydantic source precedence.
@lru_cache
def settings():
return {'feature': os.environ['APTIX_FIXTURE_FEATURE']}
os.environ['APTIX_FIXTURE_FEATURE'] = 'off'
assert settings()['feature'] == 'off'
os.environ['APTIX_FIXTURE_FEATURE'] = 'on'
assert settings()['feature'] == 'off'
settings.cache_clear()
assert settings()['feature'] == 'on'The explicit cache clear is a test mechanism, not a recommendation to add an unauthenticated production reload endpoint. A real reload must account for clients, pools and background jobs created from the previous configuration. Replacing a settings object does not automatically rebuild an HTTP client or rotate credentials already held by another component.
| Step | Environment mapping | Cached result |
|---|---|---|
| First read | off | off |
| Change mapping | on | off |
| Clear cache and read | on | on |

Validate required settings without disclosing them
At startup, reject missing or incompatible required configuration with a stable error category. Log setting names or non-sensitive revision identifiers, not secret values or complete environment dumps. A configuration fingerprint can also leak information if it is simply a hash of a low-entropy secret; use an approved version reference from secret storage where possible. Keep public health output narrower than the detailed operator configuration view.
For a controlled rollout, record configuration revision, application artifact and deployment revision together. Start a disposable instance with the replacement setting, verify the intended behavior and then promote the approved revision through the existing process. Check that background workers and scheduled jobs consume the same intended version. A frontend build-time value can require a rebuild while a backend startup value requires a new process; treating them identically creates confusing partial updates.
Choose dynamic configuration only when it is needed
If a setting must change without restart, design an explicit source, refresh interval, validation rule and fallback. State whether readers observe changes atomically and which operations retain their original snapshot. Feature flags may tolerate eventual propagation; a credential or routing change can require coordinated resource replacement. Make that distinction before implementing a generic reload function.
The saved fixture proves the three local observations and contains no customer data. Before claiming an operational fix, verify the actual deployment mechanism and process replacement. A useful incident note says which consumer retained which configuration revision and how the replacement was verified. Saying the environment was updated is only an input change until the running process demonstrably uses it.
Observability for small teams: start with the failed customer task
Bring one API or data workflow and a sanitized failure example for a bounded implementation assessment.
Why can FastAPI keep an old environment setting?
The value may already be captured in a cached settings object or startup-created resource; a deployment update needs the intended restart or explicit reload contract.
Does clearing lru_cache update every worker?
No. It affects that process’s cache; other workers and retained resource objects need their own lifecycle handling.
Should every setting support live reload?
Only when needed. Dynamic configuration requires a documented refresh, validation and resource-replacement policy.
