How do Vault dynamic secrets differ from static secrets, and why are they generally preferred for database credentials?
Quick Answer
Static secrets are stored values Vault returns as-is (like a KV secret you wrote yourself); dynamic secrets are generated on-demand by Vault at request time — for a database secrets engine, Vault actually creates a brand-new, short-lived database user/credential pair for each request, with a defined TTL after which Vault automatically revokes it. This is preferred for database credentials because it eliminates long-lived shared passwords, gives each consumer (each app instance, each CI job) its own uniquely-attributable credential, and bounds the blast radius of a leaked credential to its TTL.
Detailed Answer
A static secret in Vault's KV engine is just an encrypted key-value blob Vault stores and returns unchanged — useful for things like API keys issued by a third party that Vault doesn't control, but if that KV value leaks, it's valid until someone manually rotates it, and there's no way to tell which consumer leaked it if many services share the same static secret.
A dynamic secrets engine (database, AWS, PKI/certificates, etc.) instead has Vault actively call out to the backing system to CREATE a new credential at request time — for the database engine, Vault connects to the database using its own admin/root credential and runs a configured creation statement (e.g. CREATE ROLE ... WITH PASSWORD ... VALID UNTIL ...) to provision a brand-new, unique username and password, which it returns to the requester along with a lease and TTL. When the lease expires (or is explicitly revoked), Vault runs a corresponding revocation statement to drop that specific database role.
This gives three concrete production benefits: (1) attributable credentials — because every consumer gets its own uniquely-named database user, audit logs on the database side can show exactly which application instance or CI run performed which queries, rather than everything being attributed to one shared service account; (2) automatic expiry — a leaked dynamic credential is only useful until its TTL lapses, versus a static password that's valid indefinitely until someone notices and rotates it; (3) no credential ever needs to be written into application config or CI secrets at all — the application/pipeline authenticates to Vault (via its own auth method — Kubernetes service account, AppRole, etc.) and requests a fresh credential each time it needs one, so the actual database password is never stored anywhere outside Vault's own lease system.
Code Example
vault write database/roles/my-role \
db_name=postgres \
creation_statements="CREATE ROLE '{{name}}' WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';" \
default_ttl="1h" max_ttl="24h"
vault read database/creds/my-roleInterview Tip
Emphasize attributability (audit trail per-consumer) as a benefit alongside expiry — many candidates only mention the TTL and miss the equally important per-consumer audit angle.