---
title: "Azure Key Vault"
description: "Use Azure Key Vault for MainSDK secrets and encryption keys - managed identity, main.yaml for both driver ids, testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/azure-key-vault"
updated: "2026-10-28"
---

# Azure Key Vault

> Use Azure Key Vault for MainSDK secrets and encryption keys - managed identity, main.yaml for both driver ids, testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/azure-key-vault · Updated: 2026-10-28

Azure Key Vault can sit behind both [`secrets`](https://mainsdk.dev/docs/interfaces/secrets) and [`keys`](https://mainsdk.dev/docs/interfaces/keys): it holds your provider keys, and its keys wrap the data keys MainSDK creates for each record. Pick it when your app runs on Azure. Note the two driver ids: `azure-key-vault` for secrets and `azure-keyvault` for keys.

## Interfaces it serves

### Secrets (`secrets`)

- Status: Building for 0.2 · ships as a stable API
- Driver: `azure-key-vault` (Azure Key Vault)
- Docs: https://mainsdk.dev/docs/interfaces/secrets.md

```yaml
secrets:
  driver: azure-key-vault
```

Swap to another provider: `vault`, `aws-secrets-manager`, `gcp-secret-manager`, `doppler`, `infisical`, `env`, `local`.

### Encryption keys (`keys`)

- Status: Building for 0.3 · ships as a beta API
- Driver: `azure-keyvault` (Azure Key Vault)
- Docs: https://mainsdk.dev/docs/interfaces/keys.md

```yaml
keys:
  driver: azure-keyvault
```

Swap to another provider: `aws-kms`, `gcp-kms`, `vault-transit`, `local`.

## Before you start

1. Create a key vault in each Azure region your data must stay in, at least one per MainSDK region (US, EU and India) if you use it for `keys`.
2. Add your app's secrets, and for `keys` create one key per region.
3. Give the app a managed identity, or workload identity federation outside Azure, rather than a client secret.
4. Grant that identity read access to the secrets, and wrap and unwrap access to the keys, and nothing more.

## Configure

```yaml title="main.yaml"
secrets:
  driver: azure-key-vault        # [TBD] vault and other driver settings are not specified yet
email:
  key: secret:RESEND_API_KEY     # suggested name
keys:
  driver: azure-keyvault         # note: no hyphen in the keys driver id
  key:                           # [TBD] confirm the identifier form the driver takes
    us: https://pinecart-us.vault.azure.net/keys/pinecart-us
    eu: https://pinecart-eu.vault.azure.net/keys/pinecart-eu
    in: https://pinecart-in.vault.azure.net/keys/pinecart-in
  per-user: true
  rotate: 365d
```

## Use it

```ts title="app/lib/notes.ts"
import { keys, secrets } from "mainsdk";

export async function partnerToken() {
  return secrets.get("PARTNER_API_TOKEN");   // from Key Vault, server only
}

export async function sealNote(note: string, user: { id: string }) {
  return keys.encrypt(note, { owner: user, region: "eu", label: "personal" });
}
```

## Local development and testing

Use the `local` secrets and keys drivers in development; `mainsdk check` refuses the local keys driver in production with `MAIN-KEYS-0001`. In tests, `createTestApp()` from `@mainsdk/testing` runs both on in-memory fakes, and `chaos.on("secrets", { outage: true })` simulates Key Vault being down.

## What MainSDK adds on top

- Secrets server only, redacted everywhere, and served from memory (last good value) during an outage.
- A data key per record, one wrapping key per region, every key use audited, automatic rotation.

See [Secrets](https://mainsdk.dev/docs/interfaces/secrets) and [Encryption keys](https://mainsdk.dev/docs/interfaces/keys).

## Limits and notes

- The secrets driver comes with the config-secrets spec (phase 1); the keys driver with the keys spec (phase 1), after AWS KMS and Vault Transit.
- Azure Managed HSM comes with the hsm-keys spec in phase 3.
- `secrets.raw()` and `keys.raw()` return the provider client; `mainsdk check` lists every use.

## Swap to or from it

```yaml title="main.yaml"
keys:
  driver: azure-keyvault   # was aws-kms
```

> **Warning:** Secrets are read in place and nothing is copied, so create the same names in the new manager first. Data keys wrapped by the old key service still need it to unwrap; plan a rewrap. A guided migration between KMS drivers is not specified yet.

## FAQ

**Why two different driver ids?** The specs name them that way: `azure-key-vault` under `secrets` and `azure-keyvault` under `keys`. Use each in its own block.

**Can one vault serve every region?** For `keys`, MainSDK wants one wrapping key per region, so use a vault in each region your data lives in.

## Next

- [Secrets](https://mainsdk.dev/docs/interfaces/secrets) and [Encryption keys](https://mainsdk.dev/docs/interfaces/keys)
- [AWS KMS](https://mainsdk.dev/docs/integrations/aws-kms), [Google Cloud KMS](https://mainsdk.dev/docs/integrations/google-cloud-kms) and [HashiCorp Vault](https://mainsdk.dev/docs/integrations/hashicorp-vault)
