Keycloak → Clerk
Export Keycloak users with the CLI and create them in Clerk through the Backend API. Clerk's migration tool has no Keycloak transformer, so you map the file yourself and test one password digest before the batch.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
Keycloak
- Self-hosted realms, clients, and login flows keep identity on infrastructure you operate
- Centralized sign-in, federation, MFA, and user lifecycle controls reduce application security work
- Realm export, password algorithms, and custom providers make a cutover an operations project
- Passwords, sessions, factors, identities, and authorization policy are unusually sensitive to migration errors
Clerk
- Developer-friendly components and APIs make modern authentication and organization features quick to ship
- Centralized sign-in, federation, MFA, and user lifecycle controls reduce application security work
- Hosted UI, session behavior, metadata, and organization models can become application dependencies
- Passwords, sessions, factors, identities, and authorization policy are unusually sensitive to migration errors
Clerk: Developer-friendly components and APIs make modern authentication and organization features quick to ship. This removes a major source-side concern: Realm export, password algorithms, and custom providers make a cutover an operations project.
What you lose: Self-hosted realms, clients, and login flows keep identity on infrastructure you operate. What you inherit: Hosted UI, session behavior, metadata, and organization models can become application dependencies.
Jump to a section
Know the shape of the move.
This timeline assumes
- You can run a Keycloak CLI export with nodes stopped. The Admin Console export does not include users.
- You will call Clerk's Create User endpoint, or adapt their migration tool. The tool's documented transformers are clerk, auth0, authjs, firebase, and supabase.
- You have read the password hasher list on the current Create User reference and compared it with the algorithm in your export.
- You can tolerate a re-login. Keycloak sessions are not in the export, and Clerk sessions are new.
- You will respect Create User rate limits. Clerk tells you the endpoint is rate limited and that an export is a snapshot.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Users | partial | critical | The CLI export writes users to JSON. Clerk creates users one request at a time through Create User. A snapshot goes stale if people still change passwords in Keycloak. | Export immediately before the run, or freeze password changes. Keep the Keycloak id in Clerk externalId. |
| Password digests | partial | critical | Create User accepts a password digest plus a password hasher. Clerk says some hashers are upgraded to bcrypt on their side. If your algorithm is not on the current list, you cannot invent a hasher name. | Compare the export's algorithm with the published hasher enum. Create one user whose password you know and sign in. |
| Users without passwords | partial | high | Social and enterprise users may have no password credential. Clerk's migration tool can skip users who lack passwords, or migrate them, depending on the flag you pass. | Decide that flag in the pilot. Test a social login separately. |
| Sessions and revoked tokens | lost | high | Keycloak's export omits persisted sessions and revoked tokens. Everyone signs in to Clerk fresh. | Plan the re-login window. |
| MFA | partial | high | Create User can take a TOTP secret when the instance has TOTP enabled, with the period, length, and algorithm Clerk documents on that page. Other factor types need their own check. | Import one TOTP user and complete a challenge before you batch secrets. |
| Realms, clients, and flows | manual | critical | Clerk organizations, applications, and sessions are configured in Clerk. A Keycloak flow or SPI does not upload. | Rebuild redirects, organizations, and any claim logic in the application. Compare a token. |
| Identity providers | manual | critical | You recreate social and enterprise connections in Clerk. A federated Keycloak user does not bring the upstream link with them unless you map it. | Connect each provider and sign in once. |
| Roles and attributes | partial | high | Put Keycloak attributes you still need into Clerk public or private metadata. Roles the application checks have to be recreated in your own model. | Write the metadata map down. Read it back from the API for a sample user. |
| Rate limits and partial failure | partial | high | Clerk warns that Create User is rate limited and that a long import can drift from the source. A failed call leaves you with a partial user list. | Record the last successful id so you can resume. The migration tool has a resume-after flag if you use it. |
| Large realms | partial | medium | Keycloak wants a directory export above 50,000 users. Clerk still wants one Create User call per user, so the runtime is the limit you measure in the pilot. | Time a hundred users. Scale the window from that, not from a guess. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| Keycloak user id | externalId | transform | Clerk requires this to be unique in the instance. |
| email and emailVerified | emailAddress | transform | The first address becomes primary. Clerk can create it verified. |
| firstName and lastName | firstName and lastName | transform | Map empty values on purpose. |
| enabled false | banned or a skipped user | manual | Do not import a disabled user as a normal active user. |
| Password credential | passwordDigest and passwordHasher | manual | Only when the hasher is on the current Create User list. |
| TOTP secret | totpSecret | manual | Only if it matches the TOTP shape Clerk documents. |
| User attributes | publicMetadata or privateMetadata | transform | Private metadata stays off the frontend API. |
| Identity provider | Clerk social connection | manual | Recreate the connection, then test. |
| Authentication flow | No destination | unsupported | Rebuild behavior in the app or in Clerk's settings. |
Make the move recoverable.
Create the source-of-truth backup
Hold a CLI export of the realm before Clerk becomes the login path.
- Stop Keycloak nodes and export the realm to a directory.
- Store the user files in a restricted place. They may contain credentials.
- Count users.
- Start Keycloak again after the copy is safe.
Proof to capture: The stored user count matches Keycloak, and the files came from kc.sh export rather than the Admin Console.
Create User payloads
Map each Keycloak user onto the fields Clerk accepts.
- Set externalId to the Keycloak id.
- Set passwordHasher only to a value the current reference lists.
- Skip secrets you have not tested.
- Write failures with the user id so you can resume.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Single-user sign-in
Prove the digest before you create the rest.
- Create one user whose password you know.
- Sign in.
- Delete that user and start again if the hasher was wrong.
- Then run the batch.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
The hasher name is a guess
Create User rejects the payload, or the user is created and the password does not work.
- Consequence
- The batch is unusable.
- Mitigation
- Match the published enum and sign in once.
Stop if: The known password fails.
The snapshot goes stale
Someone changes a Keycloak password after the export.
- Consequence
- That person cannot use the new password in Clerk, or the old one.
- Mitigation
- Freeze password changes, or run a delta.
Stop if: You cannot explain a failed login for a user who changed their password.
A Keycloak claim disappears
The application still checks a claim that only a Keycloak mapper added.
- Consequence
- API calls fail or authorize the wrong user.
- Mitigation
- Compare a Clerk session token with the old token before you switch.
Stop if: A required claim is missing.
Do the work in this order.
- Days 1 to 2 · inventory
List users and claims
4 to 8 hours active1 to 2 days elapsedApp owners waiting- List password users, social users, MFA, and token claims.
- Read the current passwordHasher enum.
Depends on: Keycloak admin, Clerk secret key
Stop / go checkpointExport?
Go when: You know which hasher you will try, or you have chosen resets.
Stop when: The hasher list and the export algorithm were not compared.
- Days 2 to 4 · backup
CLI export
3 to 6 hours active1 to 2 days elapsedNode stop waiting- Export with nodes stopped.
- Count users.
Depends on: Approved inventory
Stop / go checkpointCreate the test user?
Go when: The count matches.
Stop when: The export has no users.
- Days 4 to 8 · pilot
One user, then a hundred
6 to 16 hours active2 to 4 days elapsedRate limits waiting- Create one known user and sign in.
- Time a hundred users.
- Compare one token.
Depends on: Verified export
Stop / go checkpointRun the full import?
Go when: The test login works and the token has the claims you need.
Stop when: The password or a claim fails.
- Days 8 to 12 · cutover
Create the rest and switch
4 to 12 hours active2 to 4 days elapsedCreate User rate limit waiting- Freeze Keycloak password changes.
- Finish Create User.
- Point one app at Clerk.
Depends on: Passed pilot
Stop / go checkpointSwitch the app?
Go when: Counts match and the app accepts a Clerk session.
Stop when: You cannot resume a failed batch.
- Days 12 to 15 · observe
Watch sign-ins
3 to 8 hours active2 to 3 days elapsedA day of logins waiting- Review Clerk failures.
- Keep the Keycloak export.
Depends on: Verified cutover
Stop / go checkpointRetire Keycloak?
Go when: Failures are explained.
Stop when: A provider or factor fails.
Cut over with a way back.
Cutover
Create the remaining Clerk users and send one application to Clerk.
- Freeze Keycloak passwords or take a final export.
- Resume Create User from the last successful id.
- Sign in as the known user on the production Clerk instance.
- Switch one application's keys and redirects.
- Leave Keycloak up for the other applications.
Proof to capture: Clerk's user count matches the export, and the switched app completes a sign-in.
Rollback
Return the application to Keycloak.
- Stop sending new users only to Clerk.
- Restore the Keycloak client configuration.
- List Clerk users who are not in the Keycloak export.
- Bring those accounts back only with a path you have tested.
- Confirm the app accepts Keycloak again.
Proof to capture: The app uses Keycloak, and Clerk-only users are listed.
- The known password fails on the production Clerk instance
- User counts diverge and you cannot explain the gap
- A required claim is missing
- A social connection fails
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
V-01Blocking | Count | Compare Keycloak with the CLI files. | Counts match. | Export manifest | |
V-02Blocking | Known user | Sign in to Clerk with a password you know. | The session starts. | Login note | |
V-03Blocking | externalId | Fetch a sample user from the Backend API. | externalId is the Keycloak id. | Id sample | |
V-04Blocking | Claims | Read a session token and compare it with the old claim list. | Required claims are present. | Token sample | |
V-05Blocking | Providers | Sign in with each connection. | The right user is selected. | Provider checklist | |
V-06Blocking | TOTP | Complete a challenge for one imported secret, if you imported any. | The code works, or that user is on the enrollment path. | MFA note | |
V-07Blocking | Resume log | Read the Create User error list. | Every failure is retried or accepted. | Error log | |
V-08Blocking | Test app | Point a test app back at Keycloak. | Keycloak login works. | Rollback note |
Remove the scaffolding safely.
Safe after: The production app has taken Clerk sign-ins and the Keycloak export is stored.
- Restrict the CLI export. It can hold password material.
- Remove the migration script's local copies.
- Rotate the Clerk secret key if it was exposed in a log.
- Keep Keycloak until rollback is no longer the plan.
- Record which hasher you used, and the Clerk docs date you read.
Verify against the primary material.
Platform behavior changes. Check these sources and the review dates above before executing a production migration.
- Keycloak: importing and exporting realmsAccessed 2026-11-05
- Clerk: migrating usersAccessed 2026-11-05
- Clerk: createUserAccessed 2026-11-05
- Clerk migration toolAccessed 2026-11-05