Pydantic Settings source contracts
Treat settings as two ordered phases:
configured sources -> candidate field values -> Pydantic validation -> Settings
BaseSettings is an application configuration boundary, not a global service
locator. Instantiate it once near the composition root and inject the validated
result.
Workflow
- Inspect the installed
pydantic-settings and Pydantic versions separately.
Do not infer one package's API from the other.
- Define the settings ownership boundary, field types, required values,
defaults, environment prefix, case policy, nested delimiter, dotenv policy,
secrets source, CLI use, and extra-key behavior.
- List every enabled source and its required priority. Use the documented
defaults only when they match the application contract; otherwise implement
and test
settings_customise_sources explicitly.
- Use nested Pydantic models for nested configuration. Use Pydantic secret
types for sensitive values, but do not mistake redacted representation for
storage or access control.
- Keep I/O, network secret retrieval, and business logic out of validators.
Add a narrow custom source only when built-in sources cannot express the
input contract.
- Test each source alone, source collisions, malformed values, missing
required fields, unknown dotenv keys, nested overrides, secret redaction,
and isolated environment/filesystem state.
Canonical application boundary
from pydantic import BaseModel, SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict
class DatabaseSettings(BaseModel):
host: str
port: int = 5432
password: SecretStr
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="APP_",
env_nested_delimiter="__",
env_file=".env",
extra="forbid",
)
debug: bool = False
database: DatabaseSettings
def load_settings() -> Settings:
return Settings()
Do not manually call os.getenv inside validators. Complex environment values
can use JSON decoding; nested keys override the matching top-level JSON subkey.
If a different grammar is required, make it explicit and reject ambiguity.
Source priority
Default priority can include CLI arguments when enabled, then initializer,
environment, dotenv, secrets directory, and defaults. Verify current docs and
the installed signature before relying on the exact sequence. When policy says
environment must override initializer values, return the sources in that exact
order from settings_customise_sources and test a collision.
Never commit production secrets in .env, log a settings dump, or claim that
SecretStr encrypts data. Secrets-directory file permissions, rotation, and
provider authorization remain external controls.
Completion requires isolated tests of names, conversion, nesting, precedence,
extras, missing and malformed values, and secret exposure. Read the source
model, settings recipes,
and verification matrix for nontrivial configurations.
1---2name: pydantic-settings-python3description: Use for writing, reviewing, debugging, migrating, or testing Python application configuration built with pydantic-settings. Trigger for BaseSettings, SettingsConfigDict, environment names, dotenv, secrets directories, nested settings, CLI sources, custom source precedence, and secret-safe startup configuration. Do not use for ordinary Pydantic model validation, direct os.environ access in a small script, or external secret manager administration.4---56# Pydantic Settings source contracts78Treat settings as two ordered phases:910```text11configured sources -> candidate field values -> Pydantic validation -> Settings12```1314`BaseSettings` is an application configuration boundary, not a global service15locator. Instantiate it once near the composition root and inject the validated16result.1718## Workflow19201. Inspect the installed `pydantic-settings` and Pydantic versions separately.21 Do not infer one package's API from the other.222. Define the settings ownership boundary, field types, required values,23 defaults, environment prefix, case policy, nested delimiter, dotenv policy,24 secrets source, CLI use, and extra-key behavior.253. List every enabled source and its required priority. Use the documented26 defaults only when they match the application contract; otherwise implement27 and test `settings_customise_sources` explicitly.284. Use nested Pydantic models for nested configuration. Use Pydantic secret29 types for sensitive values, but do not mistake redacted representation for30 storage or access control.315. Keep I/O, network secret retrieval, and business logic out of validators.32 Add a narrow custom source only when built-in sources cannot express the33 input contract.346. Test each source alone, source collisions, malformed values, missing35 required fields, unknown dotenv keys, nested overrides, secret redaction,36 and isolated environment/filesystem state.3738## Canonical application boundary3940```python41from pydantic import BaseModel, SecretStr42from pydantic_settings import BaseSettings, SettingsConfigDict434445class DatabaseSettings(BaseModel):46 host: str47 port: int = 543248 password: SecretStr495051class Settings(BaseSettings):52 model_config = SettingsConfigDict(53 env_prefix="APP_",54 env_nested_delimiter="__",55 env_file=".env",56 extra="forbid",57 )5859 debug: bool = False60 database: DatabaseSettings616263def load_settings() -> Settings:64 return Settings()65```6667Do not manually call `os.getenv` inside validators. Complex environment values68can use JSON decoding; nested keys override the matching top-level JSON subkey.69If a different grammar is required, make it explicit and reject ambiguity.7071## Source priority7273Default priority can include CLI arguments when enabled, then initializer,74environment, dotenv, secrets directory, and defaults. Verify current docs and75the installed signature before relying on the exact sequence. When policy says76environment must override initializer values, return the sources in that exact77order from `settings_customise_sources` and test a collision.7879Never commit production secrets in `.env`, log a settings dump, or claim that80`SecretStr` encrypts data. Secrets-directory file permissions, rotation, and81provider authorization remain external controls.8283Completion requires isolated tests of names, conversion, nesting, precedence,84extras, missing and malformed values, and secret exposure. Read [the source85model](references/settings.md), [settings recipes](references/recipes-settings.md),86and [verification matrix](references/testing.md) for nontrivial configurations.