This guide is written by the team that builds Casdoor and describes the standards as published (listed under Sources), with notes on how Casdoor implements them as of November 15, 2026. Spotted a mistake? Tell us.
Short answer: a highly available Keycloak is several identical Keycloak nodes behind a load balancer, all pointing at one highly available database. Keycloak 26 discovers the other nodes through the database by default, keeps sessions in the database, and uses Infinispan caches for performance. The database, not the Keycloak process, is the component that actually has to fail over cleanly.
This guide covers the parts that decide whether the cluster survives a node loss: discovery, caches, session affinity, the load balancer, health checks and the settings that break when you move from start-dev to a real deployment.
What high availability means in Keycloak 26
Keycloak nodes are stateless in the sense that any node can serve any request. User, client and offline sessions are persisted in the database by default; the caches in front of them are an optimization. That design is what makes a load balancer without strict session pinning possible.
A production deployment therefore has three layers:
- Two or more Keycloak nodes, running the same version and configuration.
- One shared relational database, itself replicated or managed with automated failover and backups.
- A load balancer that terminates TLS, forwards the original host and client address, and only sends traffic to healthy nodes.
Everything else is tuning.
The database is the backbone
All nodes must use the same database. Keycloak stores sessions there, and in the default configuration it also stores:
- login failure counts,
- the cluster node registry used for discovery,
- the auto-generated mTLS certificates used between cluster nodes.
This has two consequences. First, database availability is Keycloak availability; a database outage takes every node down, no matter how many Keycloak pods are running. Second, database latency is on the login path. A slow database shows up as slow logins and token refreshes, not as a Keycloak error.
Use a managed database with automated failover, or run your own with replication and tested restore procedures. Back up the Keycloak schema before every upgrade; the schema migration runs at startup and is not transactional across the whole upgrade.
Cluster discovery with jdbc-ping
Keycloak needs the nodes to find each other to invalidate caches. In Keycloak 26 the default discovery mechanism is JDBC_PING2, selected with --cache-stack=jdbc-ping. Nodes write their addresses into the shared database and read the others from it. There is no multicast, no separate registry and no extra service to run, which is why it is the default.
The alternatives have narrower uses:
- --cache-stack=kubernetes uses DNS_PING and requires the jgroups.dns.query property pointing at a headless service that resolves to the Keycloak pods.
- tcp and udp use multicast. They only work when the network allows it, and the defaults are jgroups.mcast_addr=239.6.7.8 and jgroups.mcast_port=46655.
- The cloud-specific stacks such as ec2, azure and google are deprecated.
Nodes only form a cluster if they share the same cluster name. The default is --cache-embedded-cluster-name=ISPN. Two deployments that use the same database but different cluster names will not exchange cache invalidations, which produces stale data that is hard to diagnose. Keep the default unless you are deliberately running separate clusters.
For firewalls and NAT, the cluster binds to SITE_LOCAL on port 7800 and uses port 57800 for failure detection. If the addresses Keycloak sees are not reachable by the other nodes, set --cache-embedded-network-external-address and --cache-embedded-network-external-port explicitly.
Inter-node traffic is encrypted with mTLS by default. Certificates are generated automatically, shared through the database, valid for 60 days and rotated every 30 days. That is another reason the database is on the critical path. If a service mesh already provides transport security, mTLS can be disabled, but do not disable it on a flat network without replacing it.
Caches and session affinity
Keycloak uses two kinds of caches:
- Local caches for realms, users, authorization and keys. These avoid a database read on every request and are invalidated across the cluster.
- Distributed caches for authentication sessions, user, client and offline sessions, login failures and action tokens.
One owner serves each session cache entry, and each node holds up to 10,000 session entries by default. If a request lands on a node that does not own the session, that node fetches the state from the owner. That works, but it costs a network round trip.
The documentation recommends session affinity at the load balancer: send a user to the node where the session started when possible. It is a performance recommendation, not a correctness requirement. If your load balancer cannot do affinity, the cluster still works; logins and refreshes just do more cross-node traffic.
If the cache is causing memory pressure, session caching can be disabled with spi-user-sessions--infinispan--use-caches=false. Sessions then come from the database on every request. Measure before doing this; it moves load from memory to the database.
External Infinispan is only relevant for multi-site or clusterless deployments. It is configured with --cache-remote-host, --cache-remote-port (11222), credentials and TLS options, and it requires the multi-site or clusterless feature. For a normal single-site cluster, the embedded cache is the simpler choice.
Load balancer and proxy settings
The load balancer should:
- terminate TLS, or pass it through consistently;
- preserve the original Host header;
- send X-Forwarded-For and X-Forwarded-Proto;
- health-check the Keycloak health endpoints rather than just opening a TCP connection.
Keycloak needs to know it is behind a proxy. Set KC_HOSTNAME to the public URL and KC_PROXY_HEADERS=xforwarded so redirect URLs, cookies and the discovery document use the external scheme and host. Getting this wrong produces redirect loops, cookies that are not sent, and an issuer in the discovery document that clients cannot reach.
For health checks, enable --health-enabled=true and use /health/ready for readiness and /health/live for liveness. Readiness turns healthy only when the database and the caches are usable, so it is the right probe for removing a node from the load balancer.
Kubernetes or virtual machines
On Kubernetes, the Keycloak Operator manages the deployment, the headless service and the DNS_PING configuration. Use it unless you have a reason not to; the manual path has more room for a wrong cache stack or a missing headless service.
On virtual machines, run the same container image or distribution on each node, point them at the same database, and use jdbc-ping. Do not run start-dev in production. Use start with an optimized build, a real hostname and the proxy settings above.
In both cases, size for peak login traffic rather than average. Token refresh and authorization code exchanges are cheap; a cold cache and a burst of logins are not.
What to test before calling it highly available
A cluster is not highly available until you have broken it on purpose:
- Kill one node. Logins continue, the load balancer removes the node, and no sessions are lost.
- Fail over the database. Keycloak reconnects, readiness recovers, and logins resume without restarting the nodes.
- Restart a node during a login burst. Sessions survive because they are in the database.
- Roll a configuration change. Nodes start with the same cluster name and discover each other.
- Restore a backup into a staging database. The restore actually works and the schema version matches the Keycloak version.
Also watch the database connection pool, the JVM heap and the session cache size. A heap that is too small shows up as long garbage-collection pauses during login bursts, which looks like a Keycloak problem but is a sizing problem.
Upgrades are not always rolling
Keycloak supports rolling upgrades for many changes, but not all. Recent examples: a new Dynamic Client Registration policy provider that older nodes do not understand, and an Admin API audience check that makes tokens from older nodes fail with 401 on upgraded nodes. The upgrading guide states when a rolling upgrade is not supported and tells you to shut down the cluster and upgrade all nodes together.
Treat every upgrade as a maintenance event until you have read that section. Take a database snapshot, upgrade a staging cluster first, and have a restore path.
The managed option
Running this stack well means a database with failover, a load balancer, monitoring, certificate rotation and upgrade rehearsals. If that is not where your team adds value, a managed Keycloak host or a dedicated Casdoor Cloud instance removes the operational work. We compare the hosting models and what to check before signing in managed Keycloak hosting, and the flat-price option is on the pricing page.
FAQ
Does Keycloak require sticky sessions? No. Sessions are persisted in the database and any node can serve them. The documentation recommends session affinity for performance, because it avoids cross-node cache lookups.
Which cache stack should I use? jdbc-ping, the default, unless you are on Kubernetes and prefer DNS_PING. Both use the infrastructure you already have; multicast stacks are for networks that support them.
Can I run Keycloak without a shared database? No, not for a cluster. Nodes need the same database for sessions, login failures and discovery. A single node can use a local database, but that is not highly available.
How many Keycloak nodes do I need? Two is the minimum for node failure. Three gives you room to take one node out for maintenance while keeping two serving traffic. Size by login throughput and test the failure cases rather than picking a number from a table.
Is external Infinispan required for high availability? No. It is for multi-site and clusterless deployments. A single-site cluster uses the embedded caches and the shared database.
Sources
- Keycloak: Configuring distributed caches
- Keycloak: Configuring Keycloak for production
- Keycloak: Running Keycloak in a container
- Keycloak: Using a reverse proxy
- Keycloak: Health endpoints
Product names are trademarks of their respective owners.