Rotating Secrets Automatically in Azure Key Vault

Rotating secrets manually is error-prone and easy to forget. Azure Key Vault provides rotation policies for automatic key rotation and can trigger custom functions for secret rotation via Event Grid. The two-version rotation pattern is the technique that lets you rotate any secret without causing a downtime window — and it is worth understanding even if you manage rotation manually today.

Why rotation matters and why teams avoid it

A credential that never changes is a credential that an attacker, a former employee, or a leaked log file can use indefinitely. Regular rotation limits the window of exposure: if a database password leaks and you rotate it every 30 days, the attacker’s window is at most 30 days. Without rotation, it is unlimited.

Teams avoid rotation for two reasons. First, it feels risky — changing a password that is currently working on a production system sounds like inviting downtime. Second, for many secrets there is no automation: you have to change the password in the database, update the application config, redeploy, and verify nothing broke. With multiple services using the same credential, coordinating all of this manually is genuinely complex.

Both problems are solvable, but they require designing rotation into your secret management from the start rather than adding it to an existing system.

What Key Vault can rotate automatically

Key Vault has native, zero-code automatic rotation for a small set of Azure services:

  • Azure Storage account access keys — Key Vault can regenerate storage account keys (key1 or key2) on a schedule and store the new value as a secret version.
  • Azure Cosmos DB account keys — Same pattern: Key Vault regenerates the key in Cosmos DB and updates the secret.

For these services, you configure the rotation in the Azure Portal by linking the Key Vault secret to the Azure resource. Key Vault handles the rest: calling the Azure resource management API to regenerate the key, then updating the secret value.

For everything else — SQL Server passwords, Redis passwords, third-party API keys, OAuth client secrets — Key Vault does not know how to rotate the credential because it does not have a management API for the external system. For these, Key Vault provides the notification infrastructure (via Event Grid) and you provide the rotation logic (via an Azure Function).

Near-expiry notifications with Event Grid

Key Vault integrates with Azure Event Grid to publish events when secrets approach their expiry date. The event is called SecretNearExpiry and is fired when a secret is within 30 days of expiring (this threshold is configurable).

You subscribe to this event with an Azure Function, an Azure Logic App, or any other Event Grid subscriber. The event payload includes the vault name and secret name, so your function knows exactly which secret needs rotating.

# Create an Event Grid subscription that triggers an Azure Function when a secret nears expiry
az eventgrid event-subscription create \
  --name rotate-on-near-expiry \
  --source-resource-id /subscriptions/YOUR_SUB/resourceGroups/my-rg/providers/Microsoft.KeyVault/vaults/my-vault \
  --endpoint /subscriptions/YOUR_SUB/resourceGroups/my-rg/providers/Microsoft.Web/sites/my-rotation-func/functions/RotateSecret \
  --endpoint-type azurefunction \
  --included-event-types Microsoft.KeyVault.SecretNearExpiry

Key Vault also fires a SecretExpired event after the expiry date has passed, which you can use for alerting (if a secret has expired and your function did not successfully rotate it, that is an incident).

The two-version rotation pattern

This is the most important concept in this page. If you do secret rotation with a direct swap — disable the old value, set the new value — there is a window where some application instances are still holding the old credential while others have fetched the new one. Any request that hits an instance with the old credential gets a failure. The length of this window depends on how quickly your apps restart or refresh their cached credentials, but it exists in any system where multiple instances run concurrently.

The two-version pattern eliminates this window by keeping both credential values valid simultaneously during the transition period.

Step-by-step walkthrough

Let’s say you are rotating a database password. Currently you have version 1 in Key Vault, which maps to the current database password.

Step 1: Create version 2 in the external system and in Key Vault.

Generate a new password. Set this new password on the database user — but do not remove the old password yet. The database account now accepts both the old and new passwords (most databases support this by updating the password, but keeping connections that were authenticated with the old password alive). Store the new password in Key Vault as a new secret version.

# Store the new password as a new version in Key Vault
az keyvault secret set \
  --vault-name my-vault \
  --name "db-password" \
  --value "new-generated-password-here"
# This creates version 2; version 1 still exists and is still readable

Step 2: Wait for all application instances to pick up the new version.

If your apps use versionless Key Vault references, they will pick up the new value within their resolution cycle (up to 24 hours for App Service references). If they use the SDK, they will pick up the new value on their next cache refresh or next startup. You can accelerate this by restarting your apps after creating the new version.

# Optionally restart App Service to pick up the new version immediately
az webapp restart --name my-web-app --resource-group my-rg

Step 3: Verify that all instances are using the new credential.

Check application logs for authentication errors. If you have monitoring on your database connections, verify that connections using the old credential have dropped to zero. This verification step is what makes the two-version pattern safe — you do not proceed until you have confirmed the transition is complete.

Step 4: Disable version 1.

Once you are confident all applications are using the new credential, disable the old version in Key Vault and update the database to revoke the old password.

# Disable the old version in Key Vault
# First, get the version ID of version 1
OLD_VERSION=$(az keyvault secret list-versions \
  --vault-name my-vault \
  --name "db-password" \
  --query "[?attributes.enabled == \`true\` && id != '$(az keyvault secret show --vault-name my-vault --name db-password --query id --output tsv)'].id" \
  --output tsv)

# Disable it
az keyvault secret set-attributes \
  --vault-name my-vault \
  --name "db-password" \
  --version $(basename $OLD_VERSION) \
  --enabled false

Why not just do a direct swap?

With a direct swap you: disable version 1, set the new value as version 2. The moment between disabling version 1 and all app instances picking up version 2 is your downtime window. On a system with 10 app instances that each cache the secret for 5 minutes, that window is up to 5 minutes of authentication failures. The two-version pattern makes the window zero because both values work throughout the transition.

Rotation policies for cryptographic keys

For cryptographic keys (not secrets), Key Vault supports rotation policies that automatically create new key versions on a schedule. This is most relevant for customer-managed encryption keys.

# Set a rotation policy: create a new version every 180 days
# and notify 30 days before the key expires
az keyvault key rotation-policy update \
  --vault-name my-vault \
  --name my-encryption-key \
  --value '{
    "lifetimeActions": [
      {
        "trigger": { "timeAfterCreate": "P180D" },
        "action": { "type": "Rotate" }
      },
      {
        "trigger": { "timeBeforeExpiry": "P30D" },
        "action": { "type": "Notify" }
      }
    ],
    "attributes": {
      "expiryTime": "P2Y"
    }
  }'

When a new key version is created by the rotation policy, Azure services configured to use that key with auto-rotation enabled will switch to the new version. The old version remains available for decrypting data that was encrypted under it — Key Vault does not delete old key versions automatically.

Building a rotation function

For services that Key Vault cannot rotate natively (a PostgreSQL password, a third-party API key), you write an Azure Function that implements the rotation logic. The function receives the SecretNearExpiry event from Event Grid and performs these steps:

  1. Read the current secret name from the event payload.
  2. Generate a new credential value (a random password, or call the third-party service’s API to generate a new token).
  3. Update the credential in the external system (change the database password, deactivate the old API key).
  4. Store the new credential in Key Vault as a new version of the secret.
  5. Update the secret’s expiry to a new date.
  6. Optionally restart the consuming applications.

The function needs the Managed Identity of the Function App to have Key Vault Secrets Officer permission (so it can write new secret versions) and whatever credentials are needed to update the external system.

Microsoft publishes sample rotation functions on GitHub for several common scenarios (storage accounts, Cosmos DB, SQL). Search for “azure-samples/KeyVault-Rotation” to find starting templates that implement the two-version pattern. Adapt the pattern to your specific external service rather than writing from scratch.

Common mistakes

  1. Doing a direct swap without the two-version pattern. Disabling the old secret and immediately creating the new one creates a downtime window proportional to how long your apps take to pick up the new value. Use the two-version approach to eliminate this window.
  2. Forgetting to set expiry dates on secrets. Without expiry dates, the SecretNearExpiry event never fires. Set expiry dates on all secrets that should be rotated, even if the exact date is far in the future — it ensures the notification system has something to trigger on.
  3. Purging old secret versions immediately after rotation. The previous secret version may still be in use by app instances that have not yet refreshed. Keep old versions disabled but not purged for at least as long as your application’s credential caching period (typically 24 hours for Key Vault references, or longer for SDK-based caching).
  4. Not testing rotation before an incident. The worst time to discover that your rotation function fails is during a security incident when you urgently need to rotate a compromised credential. Test the rotation process in a non-production environment to confirm it works end-to-end.

Frequently asked questions

Does Key Vault automatically rotate my secrets?

Key Vault can automatically rotate secrets for supported Azure services — specifically Azure Storage account access keys and Azure Cosmos DB access keys — using built-in rotation functions. For other secret types (like a database password or a third-party API key), Key Vault can send you a notification near expiry (via Event Grid), but the actual rotation logic — changing the password and updating the secret in Key Vault — requires a custom Azure Function that you write and connect to the event.

What is the two-version rotation pattern?

It is a pattern where you always keep two valid secret versions active simultaneously during a rotation. Version 1 is the current value. You create version 2 (the new value), deploy it to the external system, verify all your applications have picked it up, and only then disable version 1. This means there is never a moment when only the new value works but some applications are still using the old one — avoiding the downtime window that a direct swap creates.

If my app uses a versionless Key Vault reference, does it automatically pick up rotated secrets?

App Service and Azure Functions Key Vault references resolve the secret periodically — roughly every 24 hours, or immediately if you restart the app. When a new secret version is created, your app will pick it up on the next resolution cycle without redeployment. If you need the app to pick it up faster after rotation, you can trigger a restart via the CLI or the portal, or use the app restart step in your rotation function.

Last verified: 19 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.