HashiCorp Vault Dynamic Secrets and Leases Explained

Updated on
10 min read

HashiCorp Vault dynamic secrets give an application credentials created for a specific request instead of making every service share a long-lived password. This explainer is for developers, platform engineers, and security teams who need to understand how Vault authenticates workloads, generates credentials, and governs their lifetime through leases. The important distinction is that a lease is lifecycle metadata: it does not automatically make an application stop using a credential when that credential expires.

What Are HashiCorp Vault Dynamic Secrets?

Vault is a system for storing and controlling access to secrets. Its project documentation describes the platform and its integrations. A secret can be a stored value, such as an API key, or a credential created on demand by a secrets engine.

A dynamic secret is generated by a backend when an authorized client requests it. For example, Vault can use an administrative database account to create a new database user and password, return them to an application, and later remove or disable that user. The application receives a credential scoped to its own work rather than a password shared by every service.

Vault usually returns dynamic credentials with a lease: a record that includes a lease ID, a duration, and whether renewal is allowed. A lease tells Vault how long it should consider the issued secret valid and when it should attempt renewal or revocation. Static values stored in a key-value (KV) secrets engine do not become leased dynamic credentials merely because they are read from Vault.

The Problem Dynamic Secrets Solve

Long-lived credentials are difficult to manage safely. They are copied into environment files, deployment settings, logs, and developer machines; they may remain active after an employee changes roles or a service is retired. Rotation then becomes a coordinated deployment problem: every consumer must receive the new value before the old one is disabled.

Dynamic credentials reduce the period and scope of exposure. A database engine can issue a separate account for each application instance or job, apply a narrow role, and remove the account when its lease is revoked or expires. If one credential leaks, responders can target that lease instead of rotating a shared password used by unrelated services.

This does not remove the need for secure storage or careful access control. Vault itself needs an authentication method, policies, protected root credentials for backends, network access, and monitoring. Dynamic issuance is most useful when an application can obtain a credential at runtime and react when it must be renewed or replaced.

How Dynamic Secrets and Leases Work

The usual flow has two separate credentials and two control points:

  1. A workload authenticates to Vault through an enabled method, such as Kubernetes, AppRole, or a cloud identity integration. Vault issues a client token with policies that limit which paths the workload can use.
  2. The workload requests a secret from a secrets engine. The engine uses its configured backend access to create a credential or other value.
  3. Vault returns the secret data and, when the engine supports leases, lease metadata. The application uses the credential to connect to the target system.
  4. Before the lease expires, the client may ask Vault to renew it. Vault applies the configured system, mount, and role limits; a requested renewal duration is not a guarantee that the full duration will be granted.
  5. The client can revoke the lease early. At expiry or revocation, Vault asks the engine to clean up the credential where the backend supports that operation.

The Vault lease documentation explains lease IDs, renewal, and revocation. A Vault client token and a database credential are not the same thing: the token authorizes API requests to Vault, while the generated credential authenticates to the database. Either can have its own lifetime. Revoking a token can also revoke leases created under it, so token policy and renewal behavior are part of the design.

Credential model How the value is obtained Lifetime and cleanup Typical use
Static KV secret An operator stores a value; an authorized client reads it The stored value remains until changed or deleted; rotation is a separate operation Configuration that cannot be generated by a backend
Dynamic database credential Vault creates a database user for a role request A lease sets the expected lifetime; expiry or revocation triggers backend cleanup Per-service or per-job database access
OAuth access token An authorization server issues a token under OAuth rules The resource server evaluates token validity and expiry; refresh is a separate protocol action Delegated access to APIs

OAuth token expiration is not equivalent to a Vault lease: RFC 6749 defines OAuth access-token and refresh-token behavior, while Vault leases coordinate Vault-managed secret lifecycles and backend cleanup. Neither mechanism guarantees that an already established database session or a cached copy disappears at the exact moment a timer ends.

Components and Lifecycle Controls

Authentication methods establish who or what is asking. A production service should use an identity it can prove, not a root token embedded in an image or deployment manifest. Policies then grant only the capabilities needed for specific paths. A policy might permit reading one database role’s credentials without allowing the workload to change the role or configure the database connection.

Secrets engines create or return secrets. The database secrets engine supports database connections and roles that define how credentials are generated. The engine requires backend credentials with enough privilege to create and revoke application accounts; those administrative credentials must be protected and rotated independently.

TTL settings bound the lease and token lifetimes. A shorter TTL limits how long an unattended credential can remain usable, but creates more renewal traffic and more opportunities for a dependent service to fail. Choose a value based on the database’s credential behavior, application recovery time, and Vault availability rather than choosing the shortest possible duration.

Renewal and revocation require client behavior and backend support. An application should renew before expiration with enough time to retry transient errors. If renewal is denied or Vault is unreachable, it needs an explicit policy: stop using the credential, retry within a bounded window, or obtain a replacement and reconnect. Revoking a database account usually prevents future authentication, but existing database sessions can remain open until the database or application closes them.

Sealing is a separate Vault availability control. When Vault is sealed, it cannot perform normal operations that require access to its encrypted storage. Sealing does not itself close an application’s database connection or prove that every credential in an external system has been revoked. A resilient design accounts for Vault outages, backend reachability, and the behavior of applications that already hold credentials.

Leases are also different from distributed locks. A lease on a secret describes the validity and cleanup of that secret; it does not serialize arbitrary writes to another system. For coordination and stale-owner protection, see distributed locks, leases, and fencing tokens.

Real-World Use Cases

  • Application database access: Issue separate, least-privilege accounts to services, workers, or temporary jobs and remove them after use.
  • Cloud access: Generate short-lived backend credentials for automation rather than keeping a permanent access key in a repository.
  • Certificate workflows: Let an authorized workload request certificates for a service identity, while designing renewal and expiry behavior around the certificate authority and client.
  • Incident response: Revoke an affected lease or token without rotating unrelated users’ shared credentials.

These patterns work best when applications can reload credentials and recycle connections safely. In a pooled database deployment, credential rotation must account for existing sessions and pool behavior; the database connection pooling guide covers those connection lifecycle concerns. For broader service boundaries and secret-handling practices, see the microservices security guide.

Getting Started: Issue PostgreSQL Credentials

This local exercise uses Docker, PostgreSQL, Vault’s development server, and jq. The Vault dev server is intentionally insecure: it uses an in-memory store and a predictable root token. Use it only for a disposable lab, never for production or real credentials. The Vault CLI is included in the Vault container; the v shell function below runs it there.

Start an isolated network and two containers:

docker network create vault-lab
docker run -d --name vault-db --network vault-lab \
  -e POSTGRES_USER=vaultroot \
  -e POSTGRES_PASSWORD=change-this-lab-password \
  -e POSTGRES_DB=appdb \
  postgres:16-alpine

docker run -d --name vault-dev --network vault-lab -p 8200:8200 \
  -e VAULT_DEV_ROOT_TOKEN_ID=root \
  hashicorp/vault server -dev -dev-listen-address=0.0.0.0:8200

v() {
  docker exec -e VAULT_ADDR=http://127.0.0.1:8200 \
    -e VAULT_TOKEN=root vault-dev vault "$@"
}

Wait for PostgreSQL and Vault to become ready, then create a sample table:

until docker exec vault-db pg_isready -U vaultroot -d appdb; do sleep 1; done
until v status >/dev/null 2>&1; do sleep 1; done

docker exec vault-db psql -U vaultroot -d appdb \
  -c "CREATE TABLE demo_items (id integer PRIMARY KEY, name text);"

Enable the database engine, configure its administrative connection, and define a role that grants read access. The connection URL uses Vault’s database-plugin template variables:

v secrets enable database
v write database/config/postgres \
  plugin_name=postgresql-database-plugin \
  allowed_roles=app-readonly \
  connection_url='postgresql://{{username}}:{{password}}@vault-db:5432/appdb?sslmode=disable' \
  username=vaultroot \
  password=change-this-lab-password

v write database/roles/app-readonly \
  db_name=postgres \
  creation_statements='CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '\''{{password}}'\'' VALID UNTIL '\''{{expiration}}'\''; GRANT CONNECT ON DATABASE appdb TO "{{name}}"; GRANT USAGE ON SCHEMA public TO "{{name}}"; GRANT SELECT ON ALL TABLES IN SCHEMA public TO "{{name}}";' \
  default_ttl=15m \
  max_ttl=1h

Request a credential and retain its lease ID for renewal and revocation. The JSON contains a password; do not print it into shared logs or save it in a repository:

LEASE_JSON=$(v read -format=json database/creds/app-readonly)
printf '%s\n' "$LEASE_JSON" | jq '{lease_id, lease_duration, renewable, username: .data.username}'
LEASE_ID=$(printf '%s\n' "$LEASE_JSON" | jq -r '.lease_id')

v lease renew -increment=15m "$LEASE_ID"
v lease revoke "$LEASE_ID"
unset LEASE_JSON LEASE_ID

Vault’s response should show a generated username and lease metadata. Renewal asks Vault for more time within configured limits; revocation asks the database engine to remove the generated role. A production application should fetch credentials through its workload identity, keep them in protected memory, renew or replace them before expiry, and recycle connections when required. Remove the lab containers and network when finished:

docker rm -f vault-dev vault-db
docker network rm vault-lab

Common Misconceptions

  • “A dynamic secret is automatically safe.” Its permissions still come from the backend role and Vault policy. An overprivileged role can issue overprivileged credentials.
  • “Expiry instantly disconnects every client.” A lease triggers lifecycle handling; it does not guarantee that an application discarded a cached password or that a backend terminated an existing session.
  • “Vault renews everything forever.” A lease may be non-renewable, renewal can fail, and maximum TTL limits still apply. Clients need a replacement and failure plan.
  • “A Vault lease is a distributed lock.” It does not prevent concurrent work or fence stale writes. Use a coordination primitive that the protected resource can enforce.

Changelog and Last Updated

  • October 21: Initial explainer published.
TBO Editorial

About the Author

TBO Editorial writes about the latest updates about products and services related to Technology, Business, Finance & Lifestyle. Do get in touch if you want to share any useful article with our community.