Packages

Key management service with embedded OTP runtime, optional HTTP API, SQLite/PostgreSQL storage, and external RMK providers

Current section

Files

Jump to
kms docs local-vs-remote.md
Raw

docs/local-vs-remote.md

# Local vs remote KMS

KMS can run inside an application or as a remote authority service.

Choose based on trust boundary, operations, and availability needs.

## Local / embedded

Embedded mode starts `:kms` in the same BEAM VM as the application and uses `KMS.Client.Local`.

Good when:

- one app owns encrypted data;
- app-level authorization is enough;
- simple deployment matters;
- SQLite local persistence is acceptable;
- application and KMS share one trust boundary.

Tradeoffs:

- app process can call KMS as trusted/admin unless you pass `session:`;
- app host has KMS DB/RMK access;
- every app instance needs careful DB writer design if using SQLite;
- easiest operational path for small deployments.

See [Embedded KMS](use_cases/embedded.md).

## Remote service

Remote mode runs `:kms` with the optional `KMS.API` server enabled in a dedicated authority process. Apps use `KMS.Client.Remote`.

Good when:

- multiple apps need one KMS authority;
- app hosts should not hold KMS DB/RMK credentials;
- KMS needs separate deployment or access controls;
- remote API boundary is useful for operations.

Tradeoffs:

- adds network dependency to encrypt/decrypt;
- requires TLS/private network and API-token management;
- HTTP API is backend/admin surface;
- KMS authority must be monitored like critical infrastructure.

See [Remote KMS](use_cases/remote.md).

## Decision table

| Need | Prefer |
|---|---|
| Fastest Phoenix integration | Embedded |
| One app, one DB, one operator boundary | Embedded |
| App hosts must not read RMK key file | Remote |
| Multiple apps share KEKs/principals | Remote |
| Centralized audit/deploy controls | Remote |
| No network dependency during decrypt | Embedded |
| Dedicated KMS operations team | Remote |

## Authorization boundary

Local calls without `session:` are trusted/admin. That can be correct when the application has already authorized the user.

Use sessions/bindings if KMS should enforce authorization:

```elixir
KMS.decrypt_alias(ciphertext, alias_name, session: session.secret, aad: aad)
```

Remote KMS has two layers:

1. HTTP API token: app-to-KMS backend authentication.
2. KMS session: optional principal authorization inside KMS.

Do not confuse them.

## Storage boundary

Embedded:

- app host has app DB access;
- app host has KMS DB access;
- app host has local RMK key file or cloud RMK credentials.

Remote:

- app host has app DB access;
- KMS host has KMS DB/RMK access;
- app host has only remote API token.

External RMK providers can improve DB-backup separation in either mode.

## Migration path

A common path:

1. Start embedded for simple field encryption.
2. Keep aliases/AAD stable.
3. Move KMS tables/RMK material to a KMS service.
4. Switch application config from `KMS.Client.Local` to `KMS.Client.Remote`.

Plan and test key/data migration before production. Do not switch RMK providers or databases without restore validation.