Skip to content

Migration Approaches

Migrating an identity provider touches every app that authenticates against it, so the goals are: keep the auth URL, don’t force password resets, and control the cutover.

Concept bridge — Auth0 / Cognito / Ping → Keycloak

Section titled “Concept bridge — Auth0 / Cognito / Ping → Keycloak”
You have Keycloak equivalent
Tenant / User Pool / Auth0 tenant Realm
Application / App Client Client
Connection / Identity Provider Identity Provider (OIDC/SAML)
Rule / Action / Trigger / Hook Authenticator SPI / event listener
Hosted login page Realm themes (FreeMarker)
Custom claims / mappers Protocol & client scope mappers

Breaking the issuer URL invalidates live tokens and app config. We preserve it three ways:

Per-realm Frontend URL

A realm advertises https://auth.customer.com/realms/prod no matter which cell hosts it (frontendUrl override).

Hostname routing

Point CNAME auth.customer.com → our edge; the router maps host → tenant → cell.

TLS per domain

ACM + SNI (DNS-validated) or automated Let’s Encrypt at the edge.

Realm import carries hashed credentials, so users keep their passwords. What you can’t carry across vendors are private signing keys — so after a cross-vendor cutover users re-authenticate once (no password reset, just a fresh login). Options:

Export users + hashed credentials from the source and import via the Admin API / realm import. Best when the source exposes password hashes in a supported format.

Migrating the database (if you self-hosted Keycloak)

Section titled “Migrating the database (if you self-hosted Keycloak)”

Moving an existing Postgres-backed Keycloak into the platform uses standard Postgres tooling: logical replication (publication/subscription) or AWS DMS for continuous sync with minimal downtime. Physical/streaming replication isn’t available into Aurora from arbitrary sources — use logical. See Multi-Cloud for the same mechanism cross-cloud.

AWS DMS runbook (Keycloak Postgres → Aurora)

Section titled “AWS DMS runbook (Keycloak Postgres → Aurora)”
  1. Prep the source. On your Keycloak’s Postgres, enable logical decoding (wal_level = logical, sufficient max_replication_slots / max_wal_senders) and create a replication user with REPLICATION + read on the Keycloak schema. Note the DB host, port, name.
  2. Network. Give DMS a path to the source — VPC peering, VPN, or a public endpoint with SSL. The target is your platform Aurora (we provide the target endpoint + a scoped user).
  3. Create the DMS replication instance (right-sized; dms.t3.medium is fine for most).
  4. Endpoints. Create a source endpoint (your Postgres, SSL on) and a target endpoint (the platform Aurora). Test both from the replication instance.
  5. Migration task — type Full load + CDC (migrate existing rows, then stream changes). Scope it to the Keycloak schema/tables. Enable validation so DMS row-compares source vs target.
  6. Run & monitor. Watch CDCLatencySource/CDCLatencyTarget and the validation state in CloudWatch until full load completes and CDC latency is ~0.
  7. Cut over. In a low-traffic window: stop writes at the source, let CDC drain to ~0 lag, stop the task, then flip the issuer/DNS to the platform (see Cutover below).
  8. Verify login success rate + token issuance on the Analytics dashboards, then decommission the source.

Reference: AWS DMS documentation and PostgreSQL as a DMS source.

  1. Stand up the target realm(s) and configure IdPs, clients, mappers, themes.
  2. Seed users (bulk import) or wire JIT migration.
  3. Dual-run / validate — point a canary app or a fraction of traffic at the new issuer.
  4. Flip the DNS/issuer (registry change) during a low-traffic window.
  5. Watch login success rate, latency, and error dashboards (Analytics); roll back by flipping DNS if needed.