How should you actually manage secrets — env vars vs. a vault (HashiCorp Vault/AWS KMS/Secrets Manager)?
Environment variables solve the 'don't hardcode it' problem and stop there — a vault solves the much harder problems of rotation, audit, and blast radius.
LEARN BY DOINGPut your intuition to work3 steps
How should you actually manage secrets — env vars vs. a vault (HashiCorp Vault/AWS KMS/Secrets Manager)?
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.#The baseline: environment variables
Pulling secrets out of source code and into environment variables is the first, necessary step — and for a huge number of applications, it's also where the secrets story ends. A .env file (excluded from git), loaded into the process's environment at startup, beats a hardcoded API key by a wide margin. It's simple, every framework supports it natively, and it stops the single worst failure mode: a secret committed to a public repository.
But env vars have real limits that only show up once you look for them:
- No rotation without a deploy. Changing a database password means editing the variable and restarting every process that reads it — there's no way to push a new value without a redeploy or a manual restart.
- No audit trail. You cannot answer "who read this secret and when" — the variable just sits in the process's memory space, readable by anything with access to that process (including, on many systems, anyone who can inspect that process's environment on the host).
- Broad blast radius. One compromised process typically has access to every secret the service needs, not just the one it's actively using — there's no fine-grained access policy.
- Sprawl. The same database password often ends up copy-pasted into a dozen
.envfiles across services, CI pipelines, and developers' laptops, and there's no single place to revoke it. - Accidental leakage. Env vars get dumped into crash reports, logged by overly verbose error handlers, or printed by a debugging command run by someone investigating an unrelated issue.
#What a vault actually adds
A secrets manager (HashiCorp Vault, AWS Secrets Manager, AWS KMS for the encryption-key case specifically, GCP Secret Manager, Azure Key Vault) is a purpose-built service that stores secrets centrally and hands them out under policy, rather than baking them into every environment that needs them. The concrete capabilities that env vars can't replicate:
- Dynamic, short-lived credentials. Instead of one static database password shared by every service instance, Vault can generate a unique database user with a 15-minute TTL per request for a secret — if it leaks, it's already expired by the time an attacker can use it.
- Centralized rotation. Rotate the underlying secret once, in one place, and every consumer that fetches it fresh (rather than caching it forever) picks up the new value — no coordinated redeploy across a dozen services.
- Fine-grained access policy. A payments service can be granted access to the payments database credential and nothing else, enforced by the vault itself rather than by convention.
- A real audit log. Every secret access is logged with an identity, a timestamp, and a lease — which is what turns "we think we might have been breached" into "here's exactly what the compromised service could have read, and when."
- Automatic expiry. A lease that isn't renewed simply stops being valid, so a decommissioned service's access doesn't linger the way a forgotten
.envfile does on an old server nobody redeployed.
#How it actually plugs into an app
The important design point in this diagram: the application never authenticates to the vault with a static, embedded secret — it authenticates using an identity the platform already vouches for (a cloud IAM role attached to the instance, a Kubernetes service account token, a pre-provisioned AppRole credential injected at deploy time). That's what breaks the circularity of "you need a secret to get your secrets" — the bootstrap credential is scoped narrowly (it can only ask Vault for one thing) and is itself short-lived and tied to the platform's own identity system, which you're already trusting to run the workload at all.
#When the added complexity is worth it
For a small team running one service with a handful of secrets, a well-managed .env (or your cloud provider's basic parameter store, encrypted at rest, access-controlled by IAM) is a reasonable, honest choice — running a Vault cluster adds real operational overhead (another stateful system to keep highly available, unseal, and back up). The calculus flips once you have: multiple services sharing credentials, a compliance requirement that mandates rotation and audit trails (PCI-DSS, SOC 2), secrets whose compromise has outsized blast radius (a production database's admin credential, a payment processor's API key), or enough services that "redeploy everything to rotate a password" has become a genuinely painful operation.