MainSDK
Search⌘K
Integrations

Doppler

Use Doppler for MainSDK secrets - project and config setup, main.yaml, secret references, local testing and swapping.

1 interface1 driverWritten guide
Updated 2026-10-28

Doppler is a hosted secrets manager and one of the drivers behind secrets. Your app reads provider keys from a Doppler config on the server and refers to them in main.yaml as secret:NAME. Pick it when your team already keeps secrets in Doppler across environments and clouds.

Interfaces it serves

Pick Doppler in main.yaml for any of these. Your calls stay the same, and you can swap later.

Before you start

  1. Create a Doppler project for the app, with a config per environment (development, stage, production).
  2. Add each secret under the name you will reference, such as RESEND_API_KEY.
  3. Create an access token scoped to the one config each environment reads, read-only, and keep it out of code.

Configure

main.yaml
secrets:
  driver: doppler               # [to be decided] project, config and token settings are not specified yet
email:
  key: secret:RESEND_API_KEY    # suggested name; read from Doppler at startup

Use it

app/lib/partner.ts
import { secrets } from "mainsdk";   // server only

export async function partnerToken() {
  return secrets.get("PARTNER_API_TOKEN");
}

Local development and testing

Use the local driver (.mainsdk/secrets.json) or env in development, or a Doppler development config. In tests, createTestApp() from @mainsdk/testing uses the in-memory fake, and chaos.on("secrets", { outage: true }) simulates Doppler being down.

What MainSDK adds on top

  • Server-only access, with values redacted from logs, errors and telemetry.
  • The last good value served from memory during an outage (MAIN-SECRET-0007), never written to disk.
  • A key in code, a committed env file or the browser bundle fails mainsdk check.

See Secrets.

Limits and notes

  • The driver comes with the config-secrets spec (phase 1).
  • Rotated values are picked up after the driver's cache TTL, with no restart; the TTL is not decided yet.
  • secrets.raw() returns Doppler's client; mainsdk check lists every use.

Swap to or from it

main.yaml
secrets:
  driver: doppler   # was vault

FAQ

Do I still need secret: references with Doppler? Yes. They keep main.yaml free of values and make a later swap a one-line change.

Can I inject Doppler into env vars instead? Yes, with the env driver, but the doppler driver reads values directly and picks up rotation without a restart.

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet