Interview frequency: …
Short answer
Read configuration and secrets from environment variables or a secret manager at startup, convert them to a typed settings object that is validated once, and never put secrets in the code, the package, or Git.
Explanation
Separate non-sensitive defaults (such as timeouts) from credentials. Validate settings at boot so the application fails immediately with a clear message if a required secret is missing, instead of failing hours later on first use. The pydantic-settings library helps convert environment variables into a typed model, and SecretStr keeps the value out of logs and repr. Do not log all of os.environ to make debugging easier.
Code example
import os
from dataclasses import dataclass, field
@dataclass(frozen=True)
class Settings:
database_url: str = field(repr=False)
request_timeout: float = 5.0
def load_settings() -> Settings:
url = os.environ.get("DATABASE_URL")
if not url:
raise RuntimeError("DATABASE_URL is required")
return Settings(
database_url=url,
request_timeout=float(os.environ.get("REQUEST_TIMEOUT", "5")),
)Common mistakes
- Pushing a .env file containing secrets to the repository.
- Reading os.environ in scattered places in the code without central validation.