Building a Keycloak cluster with multiple instances, distributed Infinispan caching, a shared database, load balancing with health checks, and failover testing to achieve high availability.

In episode 26 you managed clients at scale. Episode 27 settles the last question before production: what if one server dies? High availability (HA) & clustering keeps the authentication service running even when a node goes down. This is the material that separates a lab setup from a deployment users actually depend on.
Keycloak is designed to run as a cluster: several Keycloak instances share one database, share caches with each other, and are served behind a single entrance. The basic concepts:
Why isn't a single node enough? Because one instance is a single point of failure: whatever the cause — crash, maintenance, or network — all logins stop. A common topology comparison:
| Topology | Advantage | Drawback | When to use |
|---|---|---|---|
| Single node | Simplest | Single point of failure | Development, low load |
| Active-passive | Cheap failover | Standby node capacity wasted | Limited budget, loose RTO |
| Active-active | Scalable and fault tolerant | Higher cluster complexity | Production with strict SLA |
Starting a Keycloak cluster means running identical instances that know each other. The required steps:
KC_CACHE_STACK determines the discovery method per environment.Each environment has a different way of making nodes aware of each other. On AWS, use the ec2 stack, which uses S3-based discovery:
kc.sh start --cache-stack ec2KC_CACHE_STACK=ec2 configures JGroups so nodes in the same region discover each other and form a cluster automatically. On Kubernetes, use the kubernetes stack, which leverages DNS-based discovery. In a typical datacenter network, the default multicast-based mode is usually sufficient. Choose the stack that matches where Keycloak runs — don't force an AWS method in another environment.
A load balancer sits in front of the cluster. Two important decisions:
/health/ready (ready to serve), /health/live (process alive), and /health/started (startup complete) endpoints. Unhealthy nodes must be removed from rotation.An NGINX configuration example:
upstream keycloak {
server kc-01.example.com:8080;
server kc-02.example.com:8080;
}
server {
listen 443 ssl;
server_name sso.example.com;
location / {
proxy_pass http://keycloak;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}The proxy headers — X-Forwarded-For and X-Forwarded-Proto — must be forwarded correctly, because Keycloak uses them to build URLs and process IPs (remember episode 24). SSL termination at the load balancer is also common: Keycloak sees a plaintext connection from the proxy, so make sure --proxy-headers is set so HTTPS links stay correct.
The database is the most sensitive point in the cluster:
Remember from the upcoming episode 28: the bigger the load, the bigger the role of database pool and cache tuning. Clustering adds nodes, but the database stays single — it's the real bottleneck most often.
The database used by all nodes also needs attention on connection timeout and idle connections: a quiet node still holds connections from the pool. Set the connection lifetime and idle limits so newly joining nodes don't struggle to get a slot in the middle of a spike.
A cluster that isn't tested isn't high availability. The mandatory routines:
Important
Clustering without failover testing is just configuration that looks tidy. Schedule failure tests periodically — nodes that haven't been tested in a while often hold surprises when they're truly needed.
Episode 27 took Keycloak to an enterprise architecture: active-active clustering with Infinispan as the distributed cache, a shared database, inter-node discovery via KC_CACHE_STACK, load balancing with health checks, database considerations, and routine failover testing.
Key takeaways:
/health/ready is used for routing decisions.In the next episode (episode 28), you'll optimize that cluster's performance: performance tuning & monitoring — from the JVM, cache, to Prometheus metrics and Grafana dashboards.