Quant Memo
Foundational

Configuration and Secrets Management

Keeping settings that vary by environment, and sensitive credentials like API keys, out of source code — so a broker password never ends up committed to a public repository and switching from paper to live trading doesn't require editing code.

Prerequisites: Version Control with Git

A broker API key is hardcoded directly into a Python file so a script can authenticate: API_KEY = "sk_live_9f8a...". That file gets committed to git, like every other file in the project. Months later the repository is made public, or a contractor is given read access for an unrelated task, and the live trading key is now visible to anyone who looks — along with every previous version of it, because git keeps full history and deleting the line in a later commit doesn't remove it from the log. This is one of the most common real security incidents in small trading operations, and it happens because configuration and secrets were treated as just more code.

Configuration is any setting that changes depending on where or how the code runs — a database address, a data directory path, whether the system is pointed at paper trading or a live account. Secrets are a specific, sensitive subset of configuration — API keys, passwords, private certificates — that must never appear in source code or version control at all. The standard fix for both is the same: keep them out of the codebase entirely, supplied instead through environment variables, a .env file that's explicitly excluded from git via .gitignore, or a dedicated secrets manager (like AWS Secrets Manager or HashiCorp Vault) that stores credentials encrypted and hands them to the running application only at startup.

Worked example. A trading system needs a broker API key, a database password, and a flag for whether it's running against the paper or live account. Instead of hardcoding any of these, the code reads them from environment variables: os.environ["BROKER_API_KEY"], os.environ["DB_PASSWORD"], os.environ["TRADING_MODE"]. The actual values live in a .env file on each machine, which is listed in .gitignore so it's never committed, and in production the values are injected by the deployment system rather than a file on disk at all. Switching the same code from paper to live trading now means changing one environment variable — TRADING_MODE=live — not editing and redeploying code, which also means the code path that runs in each mode is identical, closing off a whole class of bugs where paper and live behave subtly differently because they were different code.

What this means in practice

Nothing that would cause harm if leaked — a key, a password, a private token — should ever be typed literally into a file that git tracks, even temporarily "just for testing," because a single accidental commit is permanent in the repository's history unless the history itself is rewritten, which is disruptive and easy to get wrong. Treating configuration as external to the code, rather than baked into it, also has a second benefit beyond security: it's what makes production-research parity possible, since the same code can run against different environments purely by changing what's fed to it from outside.

Secrets and environment-specific configuration belong outside source code — in environment variables, an untracked .env file, or a secrets manager — never hardcoded or committed. This prevents credential leaks and lets the same code run correctly across paper, staging, and live environments.

Adding a secret to .gitignore after it's already been committed does not remove it from git history — every prior commit still contains it, retrievable by anyone with repository access. A leaked secret must be rotated (issued fresh and the old one revoked), not just deleted from the current file.

Related concepts

Practice in interviews

Further reading

  • The Twelve-Factor App, "Config"
ShareTwitterLinkedIn