Skip to content

Migrating from sandbox to live

Sandbox and live are separate environments. A live rollout is a configuration and credential promotion, not an in-place conversion of sandbox data.

Environment mapping

SettingSandboxLive
API keysk_test_...sk_live_...
SDK modetestlive
Base URLstaging Gateway URLproduction Gateway URL
Session livemodefalsetrue
Webhook signing secretstaging secretproduction secret
Data and queuesstaging bindingsproduction bindings

API keys can also carry an optional absolute expires_at timestamp. Keep short-lived sandbox keys for CI and pre-production access, and provision a separate future expiry for live credentials according to your rotation policy. An expired key is rejected by the Gateway even if it was previously cached. The key lifecycle resources also expose last_used_at; it is null until the first successful authentication and is updated asynchronously with a bounded write frequency.

Newly issued keys are also bound to their environment at rest. The Gateway rejects a key whose stored environment does not match the current deployment, in addition to rejecting sk_test_/sk_live_ prefix mismatches. Legacy operator-provisioned keys without this metadata remain valid during migration; new provisioning and rotation write the binding automatically.

Restricted-key management is least-privilege: api_keys:manage can list, rotate, and revoke tenant keys, while a child key may only delegate scopes it already has. A session-only key cannot manage keys or account-level webhooks.

Webhook verification accepts an optional atomic replayStore. Use a shared Redis/KV/Durable Object implementation in production; the SDK's createMemoryWebhookReplayStore() is intended for local development and single-process tests only. A delivery is claimed after signature and JSON validation, and a second attempt within the signature tolerance raises DlbrIdWebhookReplayError.

Keep these values in separate secret-manager scopes. Do not copy a sandbox key, webhook secret, tenant database record, or trust-store material into production.

1. Freeze the integration contract

Before provisioning live credentials, confirm that the production deployment supports the same API version used by the application:

ts
const id = new DlbrId({
  baseUrl: process.env.DLBR_ID_BASE_URL!,
  apiKey: process.env.DLBR_ID_API_KEY!,
  mode: process.env.DLBR_ID_MODE === "live" ? "live" : "test",
  apiVersion: "2026-09-21",
});

Use one explicit configuration object per deployment. Do not infer live mode from a hostname alone.

2. Provision live credentials separately

An operator creates a production key and webhook endpoint in the production environment. The plaintext key and signing secret are shown once.

sh
cd apps/gateway
pnpm run provision:client -- \
  --client-id acme-bank \
  --allowed-origins https://app.acme.example \
  --remote

The production command defaults to the production D1 database and emits an sk_live_... key. Use a separate production webhook endpoint and verify its delivery before switching traffic.

3. Configure live secrets atomically

Update the application deployment as one change:

text
DLBR_ID_BASE_URL=https://<production-gateway>
DLBR_ID_API_KEY=sk_live_...
DLBR_ID_MODE=live
DLBR_ID_WEBHOOK_SECRET=whsec_live_...

Never put these values in NEXT_PUBLIC_*, client-side JavaScript, URLs, or logs. The SDK will reject mode: "live" with a test key and requires an HTTPS base URL.

4. Run a production preflight

Before allowing customer traffic, create one controlled verification session and assert the environment metadata:

ts
const session = await id.sessions.create({
  credentials: [{
    format: "mso_mdoc",
    issuer_id: "https://issuer.example",
    namespace: "org.iso.18013.5.1",
    claims: ["given_name"],
  }],
});

if (!session.livemode) {
  throw new Error("Live deployment returned a sandbox session");
}

Verify the webhook with the live signing secret and record the returned requestId for the rollout log. Do not use real customer identity data for a preflight unless the approved production test procedure requires it.

5. Switch traffic and monitor

Use a gradual application rollout where available. Monitor:

  • session creation error rate and requestId correlation;
  • livemode values in server-side telemetry;
  • webhook delivery and signature verification failures;
  • rate limits and retry volume;
  • audit-log entries in the production tenant.

The SDK's onRequest callback is suitable for metrics, but redact API keys, claims, QR URLs, and webhook bodies from telemetry.

Rollback

Rollback is a configuration switch, not a key mutation:

  1. Stop new live traffic at the application layer.
  2. Restore the last known-good live configuration or route new traffic back to sandbox only for test tenants.
  3. Do not send live customer sessions to sandbox.
  4. Revoke the live key if compromise is suspected; otherwise keep it disabled until the incident is understood.
  5. Use the captured requestId values to investigate Gateway errors.

Existing live sessions remain live sessions. A rollback must not retry their identifiers against sandbox.

Post-migration cleanup

  • Confirm the production key is stored and access-controlled.
  • Revoke temporary preflight keys.
  • Confirm staging and production webhook secrets are distinct.
  • Update the runbook with deployment version, API version, key IDs, and preflight request ID — never plaintext secrets.
  • Keep sandbox credentials available for non-production QA; do not delete them as part of live promotion.

Built for developers integrating privacy-preserving identity verification.