Rotating Secrets Safely with Vault KV v2 Versioning
Vault KV v2 stores every write as a numbered version, so teams can rotate credentials, audit changes, and roll back without external tools.
29 Mar 2026, 14:52 UTC

When an application database password leaks or a deployment pushes a bad TLS certificate, teams often rotate the secret by overwriting the old value. Without versioning, there is no record of what the previous value was, when it changed, or which workload used it. That makes audits difficult and rollback risky.
HashiCorp Vault’s KV v2 secrets engine treats every write as a new, numbered version. You can store a secret, retrieve any earlier version by number, and remove obsolete versions when they are no longer needed. This works for database passwords, API tokens, and configuration data without external version-control tooling.
Enable KV v2 and confirm the mount
KV v2 is available from Vault 1.5 onward. Older installations run KV v1, which stores only the latest value. Check the server version first:
vault --version
Run this on the machine with the Vault CLI installed. No special permissions are required just to read the version.
If the server is 1.5 or newer, enable the engine at a path of your choice. This changes server state, so use a token with the sudo capability or the root token:
vault secrets enable -path=secret kv-v2
Confirm the mount type with:
vault secrets list
Look for secret/ in the list with type kv-v2. If the path already exists as KV v1, you cannot convert it in place; create a new path or migrate data manually.
Write a secret and read an exact version
Storing a value creates version 1 automatically. Replace the placeholder with a real password:
vault kv put secret/db password=
This requires write permission on secret/data/db. A token without write rights receives a permission denied error.
Read the latest value:
vault kv get secret/db
Read version 1 specifically, which is useful when rolling back after a bad rotation:
vault kv get -version=1 secret/db
List all available versions for a key:
vault kv get -versions secret/db
The first write is always version 1; there is no version 0.
Trade-off: storage and version growth
Every vault kv put creates another version. More versions consume more storage and add a small amount of read latency because Vault must locate the requested version in its index. KV v2 does not include a built-in max_versions limit that prunes old values automatically.
To control growth, review old versions on a schedule and remove ones you no longer need. Permanent deletion is destructive: applications or scripts caching an older value will fail if they request it later. Check vault kv --help for your Vault version to find the correct delete or destroy flag before running it against production data.
After any cleanup, verify the result:
vault kv get -versions secret/db
Confirm the remaining version list matches your retention policy.
Actionable closing: protect, back up, and verify
Start by enabling KV v2 if it is not already active. Then write a Vault policy that limits who can read or delete history. This example allows applications to read and list, but not delete:
path \"secret/data/db\" {\n capabilities = [\"read\", \"list\"]\n}
Attach the policy to application tokens so they cannot accidentally remove old versions.
Include versioned secret data in your backup strategy. vault operator backup captures the storage backend; after a restore, run vault kv get -versions secret/db to confirm the version history survived.
Treat version pruning as a manual, reviewed operation until you are certain no workload depends on a previous secret value.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.