Renew Vault Leases in Long-Running Workers

A short-lived request handler authenticates to Vault, reads a secret, and exits — nothing to renew. A long-running worker is different: its token and its dynamic database lease both expire on a TTL, and if it never renews them it starts throwing permission errors an hour into the job. This page keeps a HashiCorp Vault session alive with hvac, complementing the dynamic database credentials and AppRole workflows.

Problem 1: authenticate once, never renew

# ANTI-PATTERN
client.auth.approle.login(role_id=RID, secret_id=SID)   # token expires in 1h
while True:
    do_work(client)   # PermissionError once the token TTL lapses

The token silently expires mid-job and every subsequent call fails.

Key APIs in Problem 1: authenticate once, never renew The main identifiers used in Problem 1: authenticate once, never renew RIDSIDPermissionErrorTTLrole_id=RIDsecret_id=SID
The APIs and identifiers this section uses.

Problem 2: ignoring the database lease

Even with a live token, the dynamic database credential has its own lease. When it expires the database rejects the connection, even though Vault itself is still reachable.

Problem 2: ignoring the database lease The core point of Problem 2: ignoring the database lease ignoring the database leaseEven with a live token, the dynamic database credential has its own lease.
The key point of this section at a glance.

Secure implementation

Renew the token and the lease before expiry, and re-authenticate on failure.

# vault_session.py
import time
import hvac


class VaultSession:
    def __init__(self, url, role_id, secret_id):
        self.url, self.role_id, self.secret_id = url, role_id, secret_id
        self.client = hvac.Client(url=url)
        self._login()

    def _login(self):
        self.client.auth.approle.login(role_id=self.role_id, secret_id=self.secret_id)

    def maintain(self, lease_id: str):
        """Call periodically from the worker loop (e.g. every 60s)."""
        try:
            self.client.auth.token.renew_self()          # extend the token TTL
            self.client.sys.renew_lease(lease_id=lease_id)  # extend the secret lease
        except hvac.exceptions.InvalidRequest:
            self._login()                                # token/lease gone -> re-auth
            return "reauthenticated"                     # caller should refetch + reconnect
        return "renewed"

Renew at half the TTL from the worker loop; on InvalidRequest, re-authenticate, fetch a fresh credential, and reconnect the database client.

Key APIs in Secure implementation The main identifiers used in Secure implementation VaultSessionClientCallTTLInvalidRequestvault_session.py
The APIs and identifiers this section uses.

Gotchas & version-specific behaviour

  • A lease has a max TTL; past it, renewal fails and you must fetch a new dynamic credential.
  • renew_self extends the token but not any secret leases — renew both.
  • Recreate the database engine/connection pool after refetching credentials; old connections keep the expired password.
  • Add jitter to the renewal interval so a fleet of workers does not renew in lockstep.
  • Handle Vault being briefly unreachable with retries; do not crash the worker on one failed renew.
Gotchas & version-specific behaviour Key points from Gotchas & version-specific behaviour A lease has a max TTL; pasti…renew_self extends thetoken …renew both.Recreate the databaseengine/…Add jitter to the renewalint…Handle Vault being brieflyun…
The essentials of Gotchas & version-specific behaviour.

Production parity checklist

  • Renew token and lease at roughly half their TTL from the worker loop.
  • Re-authenticate and reconnect on InvalidRequest rather than crashing.
  • Rebuild the connection pool when the dynamic credential is replaced.
  • Add jitter to renewal timing across the worker fleet.
  • Alarm on repeated re-authentications, which signal a TTL that is too short.
Production parity checklist Key points from Production parity checklist Renew token and lease atroug…Re-authenticate andreconnect…Rebuild the connection poolw…Add jitter to renewaltiming …Alarm on repeatedre-authenti…
Every item to tick off for Production parity checklist.

Frequently asked questions

Why does my Vault-authenticated worker start failing after an hour?

Vault tokens and dynamic secret leases have a TTL. A worker that authenticates once and never renews loses access when the token or lease expires. Renew both before expiry, or re-authenticate and reconnect when they lapse.

Should I renew the token or fetch a new secret?

Renew while you can — it is cheaper and keeps the same credential. When a lease reaches its max TTL it cannot be renewed further; then fetch a fresh dynamic credential and reconnect the client that uses it.

How early should I renew a lease?

Renew at roughly half to two-thirds of the TTL so a transient failure still leaves time to retry before expiry. Never wait until the final seconds.

Key takeaways

A long-running worker must renew both its Vault token and its secret lease before expiry, and re-authenticate then rebuild its connections when a lease reaches its maximum TTL.