KV v2 versioning and check-and-set
Static secrets without stampeding them.
In short. Not every secret can be dynamic. Third-party API keys, partner credentials, and some legacy systems still need a stored value.
Not every secret can be dynamic. Third-party API keys, partner credentials, and some legacy systems still need a stored value. KV version 2 is Vault's versioned key-value store: every write creates a new version, deletes are soft by default, and check-and-set (CAS) prevents two operators from blindly overwriting each other.
Teams treat KV like a shared folder and then wonder why a rollback is impossible or why a deleted key still haunts them. Versioning is the feature; discipline is still required — short policies, no world-readable mounts, and rotation notes in metadata.
Enable KV v2 and write versions
Fresh Vault installs often mount secret/ as KV v2 already. If you enable it yourself, set -version=2. Writes go to .../data/.... Reads can pin ?version=N. Metadata endpoints show version history and custom metadata fields useful for ownership (owner=payments-team, rotate_after=2026-10-01).
vault secrets enable -path=secret kv-v2vault kv put secret/payments/stripe api_key=sk_live_examplevault kv put secret/payments/stripe api_key=sk_live_rotatedvault kv get -version=1 secret/payments/stripevault kv metadata get secret/payments/stripe
====== Data ======api_key sk_live_exampleversions0 1 2... current_version=2
Check-and-set and safe deletes
CAS uses the current version as a precondition: vault kv put -cas=2 ... fails if version 2 is no longer latest. That stops silent clobbering during dual-admin edits. Soft delete marks versions deleted without destroying data; destroy and metadata delete are the irreversible steps. Know which one your runbook means by "delete."
What KV is not
KV does not mint database users, does not rotate cloud keys by itself, and does not replace PKI. If a credential can be dynamic, prefer the database/cloud engines. Use KV for truly static material, keep TTLs on the wrapping tokens that deliver it, and audit every read. Pair with Vault Agent so apps read a file refreshed from KV instead of long-lived env vars copied everywhere.
Going deeper
Versioning also changes incident response. When someone writes the wrong API key, you can read the previous version, restore it deliberately with CAS awareness, and destroy the bad version after you confirm no consumer still needs it. That is a different operational muscle than "overwrite the file in the password manager and hope."
Custom metadata fields are underrated. Put owner, ticket, and rotate_after on the secret metadata so automation and humans share one inventory without a second spreadsheet. Policies can still deny metadata writes to app roles while allowing data reads — split those capabilities consciously.
Replication and DR apply to KV like anything else in raft: a restored snapshot restores versions. Practice reading an old version after restore so you know whether your runbooks assume soft-deleted versions survive. Document destroy as a deliberate compliance action with dual control, not a casual cleanup.
Try this
Write two versions, read version 1 explicitly, soft-delete, confirm current read fails, then undelete.
vault kv put secret/lab/demo password=onevault kv put secret/lab/demo password=twovault kv get -version=1 secret/lab/demovault kv delete secret/lab/demovault kv get secret/lab/demo || truevault kv undelete -versions=2 secret/lab/demovault kv get secret/lab/demo
password oneError: ... version has been deletedpassword two# SUCCESS — soft delete + undelete loop
Takeaway
KV v2 gives versioned static secrets with CAS and deliberate delete semantics. Use it sparingly, policy it tightly, and prefer dynamic engines when the dependency allows.
Next: dynamic database and cloud credentials — secrets that expire without a calendar invite.