Moving secrets out of files and into a managed store is the single largest improvement most systems can make to their credential handling. It gives you access control, audit logging, versioning and — with some backends — automatic rotation.
What each backend gives you
AWS Secrets Manager — native rotation via Lambda, IAM-based access control, CloudTrail audit. The only one here with genuinely automatic rotation for supported services like RDS.
HashiCorp Vault — the most capable, and the most operationally demanding. Its dynamic secrets engine issues short-lived database credentials on demand, which removes the long-lived secret entirely.
Google Secret Manager — versioned, IAM-controlled, straightforward. Rotation is manual.
Azure Key Vault — versioned with soft delete. Note that previous versions stay retrievable until explicitly disabled.
Doppler — developer-focused, with good local development integration.
The shell history problem
Every write command shown here passes the secret as a command-line argument, which is how the documentation presents them and how most people run them. That writes the secret to your shell history file in plaintext, and makes it visible in ps output to any other user on the machine while it runs.
For anything real:
# Read from a file, then destroy the file
aws secretsmanager create-secret \
--name 'production/api' \
--secret-string file://payload.json
shred -u payload.json
# Or pipe from stdin
echo -n "$SECRET" | gcloud secrets create api --data-file=-Rotation differs sharply between backends
This is where the backends genuinely diverge, and the rotate panel reflects it honestly.
AWS can rotate supported secrets automatically on a schedule. Vault does not rotate arbitrary KV values at all — you write a new version and must explicitly destroy the old one, since old versions remain readable by default. Google and Azure both keep previous versions accessible until you disable them, which surprises people who assume writing a new value revokes the old one.
Writing a new version is not revocation. Destroy or disable the old one explicitly.
A secrets manager only helps if applications read from it
The common failure is using a secrets manager as a storage location, then copying values out into a .env file at deploy time. That recreates every problem the manager solved: the value sits in plaintext on disk, rotation requires a redeploy, and there is no audit trail of who read it.
Read from the manager at application startup, or use a sidecar or CSI driver that injects secrets at runtime. Then rotation is a write to the manager and a pod restart.
Frequently asked questions
Which backend should I choose?
Whichever your cloud already provides — the IAM integration is the valuable part. Vault if you are multi-cloud or want dynamic secrets. Do not run Vault for a handful of static secrets; the operational burden is real.
How much do these cost?
AWS charges per secret per month plus per API call, so caching matters at volume. Google and Azure are similar. Self-hosted Vault is free to license and costs you operational time instead.
Can I store a whole .env in one secret?
Yes, as JSON, which is what the payload here produces. It is one API call to fetch everything. The trade-off is coarser access control: any service that can read the secret reads all of it. Split by service when that matters.
What about secret zero?
The credential your application uses to authenticate to the secrets manager. Solve it with workload identity — IAM roles for service accounts, Kubernetes service account tokens, or instance metadata — so there is no static credential to protect at the bottom of the chain.