When I set up a Keycloak cluster at work two years ago, I wanted to take a simple but “complete” approach and have as few links to other systems as possible that could affect operations. You wouldn’t want to have a single point of failure or circling dependencies. That’s why I decided at the time that every server with a Keycloak instance would also maintain a replication of the database.
At the time, I used MariaDB+Galera for this. Galera has the nice feature that you can set up multi-master replication without much effort. Other DBMSs can do this too, but usually only in active-standby mode or with a maximum of two servers. I had repeatedly asked myself whether this was the right decision and rehearsed what to do “in case of an emergency” if I wanted to switch from MariaDB to a different DBMS.
At our company, we have managed SQL Server clusters and many instances. In an experiment, I therefore tried to switch from MariaDB to SQL Server using the tools and commands provided by Keycloak.
Step 1: Create a backup
Before you start making any changes to your database or your configuration, you should back up both and make sure that you can restore them in case of emergency.
Step 2: Disable all User Federation Providers
Info You only need to complete these steps once per cluster, except for configuring the new database.
During my tests, I noticed that an active user federation provider (e.g., to an Active Directory) causes problems and deadlocks, followed by timeouts. Why? Because Keycloak initially synchronizes all information with the provider when starting the instance, while at the same time generating the database export.
So If possible, disable all User Federations (you don’t need to delete them) and stop the Keycloak server to avoid any conflicts or locks. Connections to other Identity Providers are fine.
Step 3: Export one or all realms
Go to your server and run the following command. Adjust your paths if necessary:
cd /opt/keycloak
./bin/kc.sh export --dir /opt/keycloak/export --users different_files --users-per-file 1000
This will export all realms to the directory /opt/keycloak/export/master. Please be careful, as those files contain
the full configuration of your realms, including the private keys and client secrets.
Step 4: Change your Keycloak configuration to use the new DBMS
See the Keycloak documentation as to what DBMS are compatible and how to configure them. After configuration, you can start the Keycloak server to bootstrap the new database. Stop the instance afterwards.
db=mssql
db-url-host=your-db-server-name
db-url-port=1433
db-username=keycloak
db-password=keycloak
db-url-database=keycloak
# Add this line if you are using a self-signed certificate and have TLS enabled
# or add the root certificate to your trust store
db-url-properties=;trustServerCertificate=true
Step 5: Import the data
Depending on the size of your realm, this may take a while to import all users and clients.
./bin/kc.sh import --dir /opt/keycloak/export --override false
During the import you may encounter some errors. See the Troubleshooting section for more.
After that is done, you can start the Keycloak server again. You should be able to login to your Keycloak instance using the same credentials as before.
Troubleshooting
Database is locked/timeout
If you run into timeouts or database locks, you can tune the default transaction timeout with the following argument:
-Dquarkus.transaction-manager.default-transaction-timeout=3600
Additionally, you may increase or decrease the number of parallel users being imported by adjusting the --users-per-file
argument during the export.
Import error Script upload is disabled
2025-06-21 21:02:51,110 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (development) mode
2025-06-21 21:02:51,110 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Script upload is disabled
This error means that the realm you are trying to import is from before Keycloak 18 (2022). Before that date, Keycloak did support adding custom JavaScript to the authorization flows. This is since then no longer the case. In my opinion, this is an oversight by them, because it was exported just fine…
If you need the authorization policies, I suggest you check the official migration guide: https://www.keycloak.org/docs/latest/server_development/#_script_providers
In case you don’t need them, you can just edit the realm file and remove all authorizationSettings nodes from the JSON object.