Python

Verified against ChatGPT · 2026-08-04

Build a pydantic-settings config loader with real local/staging/production profiles

A prompt for a pydantic-settings BaseSettings hierarchy with per-environment overrides, fail-fast validation on missing secrets, and a clear precedence order between env vars and .env files, instead of an ad hoc os.environ.get scattered across the codebase with silent string defaults.

Claude CodeChatGPT (GPT-5.1)GitHub Copilot Chat4 fillable variables

The prompt

Ready to copy — highlighted parts are example details you can swap.

Build a configuration system using pydantic-settings for the application below. The goal is one typed Settings object the whole app imports, not os.environ.get(...) calls scattered across a dozen files with inconsistent, silently-wrong string defaults.

APPLICATION
A FastAPI service currently reading DATABASE_URL, API_KEY, and DEBUG via scattered os.environ.get() calls with inconsistent defaults.

REQUIRED SETTINGS
database_url: PostgresDsn, api_key: str (secret), debug: bool, request_timeout_seconds: int, allowed_origins: list[str]

ENVIRONMENTS
local (debug=True, permissive CORS), staging (debug=False, staging DB), production (debug=False, strict CORS, must fail startup if debug is somehow True)

SECRETS HANDLING
api_key and database_url are secrets, injected by the deployment platform as real environment variables in staging/production — never read from a checked-in .env there.

REQUIREMENTS
1. Define a base Settings(BaseSettings) class typing every setting explicitly — no bare str for something that's really an int, a bool, or a URL (use pydantic's AnyUrl or a more specific type where it fits). Use model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="forbid") so an unrecognized environment variable typo raises loudly instead of silently being ignored.
2. Implement local (debug=True, permissive CORS), staging (debug=False, staging DB), production (debug=False, strict CORS, must fail startup if debug is somehow True) as either a single Settings class with an environment: Literal[...] field driving conditional defaults, or as one subclass per environment — pick whichever fits database_url: PostgresDsn, api_key: str (secret), debug: bool, request_timeout_seconds: int, allowed_origins: list[str] better and say why. Whichever approach, the environment itself must be selected by one explicit variable (e.g. APP_ENV), never inferred from something indirect like "is DEBUG unset."
3. Any setting with no safe default — a database password, an API key, anything in api_key and database_url are secrets, injected by the deployment platform as real environment variables in staging/production — never read from a checked-in .env there. — must be a required field with no default value at all, so the application fails at startup with a clear pydantic ValidationError naming the missing field, rather than starting successfully and failing confusingly the first time that setting is actually used.
4. State the precedence order explicitly and make sure the implementation matches it: real environment variables should override .env file values (this is pydantic-settings' actual default behavior), which should override class-defined defaults — confirm this matches what local (debug=True, permissive CORS), staging (debug=False, staging DB), production (debug=False, strict CORS, must fail startup if debug is somehow True) actually needs for a production deploy where env vars come from the deployment platform, not a checked-in file.
5. Never commit real secret values — provide a .env.example with every required variable name present and a placeholder or empty value, and add .env to .gitignore if it isn't already covered.
6. Add a small validator (@model_validator) for any cross-field consistency local (debug=True, permissive CORS), staging (debug=False, staging DB), production (debug=False, strict CORS, must fail startup if debug is somehow True) implies — e.g. if environment is "production", debug must be False, and say what happens if that combination is ever set: fail startup, don't just log a warning and continue.
7. Give the Settings object a __repr__ or a dedicated logging call at startup that prints every loaded setting except the ones flagged in api_key and database_url are secrets, injected by the deployment platform as real environment variables in staging/production — never read from a checked-in .env there. — an operator restarting the service needs to be able to confirm which environment and config actually loaded without that confirmation ever risking printing a real credential to a log line.

OUTPUT FORMAT
1. The Settings class(es).
2. The .env.example file.
3. One sentence confirming the precedence order and how a missing required secret actually surfaces at startup.
4. Confirmation that the startup log/repr excludes every field flagged as a secret.

Customize

Optional — swap in your own details for the highlighted parts above.

Why this works

Requiring extra="forbid" in the settings config targets a real and specific class of bug: without it, a typo in an environment variable name (DATABSE_URL instead of DATABASE_URL) is silently ignored by pydantic-settings rather than raising, so the application starts successfully, the setting quietly falls back to its default (or fails validation on a completely different, more confusing field), and the actual typo is invisible until someone traces a wrong runtime value all the way back to a one-character misspelling in a deployment config. Making required-with-no-default the rule for secrets, rather than a fallback empty string, exploits Pydantic's validation timing directly: a missing required field raises ValidationError the moment Settings() is instantiated, which for a well-structured app happens once at process startup — so a missing production database password fails loudly in the first second of a deploy, rather than starting up "successfully" and only surfacing as a mysterious connection error the first time a request actually needs that database, at which point the failure is much further from its actual cause and much more disruptive to debug live. The precedence-order requirement matters because pydantic-settings' actual behavior (real environment variables override a .env file, which overrides class defaults) is exactly backwards from what someone might assume if they're thinking of a .env file as "the config" and env vars as an occasional override — in a real production deploy, the platform injects secrets as actual environment variables and there often is no .env file at all, so a settings design that was only ever tested locally against a .env file can behave completely differently in production if the precedence direction was misunderstood, which is precisely the kind of bug that never shows up until the first real deploy. The startup-visibility requirement, scoped explicitly to exclude flagged secrets, closes the loop on a common operational blind spot: without any confirmation of what actually loaded, a misconfigured deploy that silently picked up the wrong environment profile looks identical to a correct one until something downstream fails, and the fix has to be a log line disciplined enough to be genuinely useful without becoming a second, less obvious place a credential could leak.

Verified against

ChatGPT GPT-5.1 · 2026-08-04

Changelog

  • 2026-08-04 Initial publish, verified against ChatGPT (GPT-5.1) on pydantic-settings 2.6.

Need this built into your business?

If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.

EXPLORE CUSTOM SOFTWARE
All Python prompts

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY