Keycloak is a full identity and access management server covering OIDC, OAuth 2.0, SAML, user federation, fine-grained authorization and multi-realm tenancy. It replaces Okta, Auth0 or Entra ID for organizations that want the protocol coverage without the per-user bill.
Our verdict on Keycloak#
Keycloak is the most capable thing in this category and the most work. The Quarkus rewrite is finished and it was not cosmetic: Quarkus became the default distribution in 17.0.0, the WildFly distribution was removed outright in 20.0.0, and the old keycloak-containers repository is archived. Anything you read about standalone.xml, the JBoss CLI or the jboss/keycloak image is dead information. Its upgrade path is the hardest here because each version migrates the schema on first start and the migration does not run backwards, so a rollback means restoring PostgreSQL rather than repulling a tag. 26.0 removed hostname v1, replaced the proxy option with proxy-headers, switched Infinispan marshalling to Protostream and cleared every cache in the process. 26.7 (July 2026) at least made zero-downtime patch upgrades the default within a major.minor stream. Choose it if you need SAML, realms or fine-grained authorization; otherwise you are funding a JVM and a migration budget for nothing.
Who Keycloak is for#
Choose it if
- You need SAML, OIDC, token exchange and policy-based authorization from one server, and the alternatives cover three of the four.
- Multi-tenant setups: realms give genuinely separate user populations with separate branding, policy and signing keys.
- Small businesses that need something an auditor recognizes. It is a CNCF incubating project with a Red Hat product built on it.
- Teams that already run Java and PostgreSQL in production and have real upgrade windows.
Look elsewhere if
- You have one host and five apps. You will spend more evenings on hostname and proxy settings than on the apps you wanted to protect.
- You cannot commit to reading migration notes for every major you pass through. There is no supported way to jump three majors and hope.
- You have under 2 GB of RAM free. The container guide suggests 2 GB for Keycloak alone, before PostgreSQL gets any.
What running it actually looks like#
Two containers minimum: Keycloak and PostgreSQL. start-dev gets you running in one line (KC_BOOTSTRAP_ADMIN_USERNAME, KC_BOOTSTRAP_ADMIN_PASSWORD, port 8080) but it uses the dev-file H2 database and disables hostname checks, and it is not something you keep. Production is start, which refuses to boot until you have supplied KC_HOSTNAME, a real database, and either TLS or an explicit --proxy-headers setting. For sane startup you bake an optimized image: run kc.sh build at image build time with your database vendor and feature flags fixed, then run start --optimized. Health and metrics are not on the main port, they live on the management interface at 9000. First boot against an empty database runs the full Liquibase migration, which is the step to watch on every subsequent upgrade too.
Resource profile#
- Memory
- 750 MB idle, around 1250 MB in ordinary use. A JVM. The container guide says give it at least 750 MB and suggests 2 GB for production; the sizing guide budgets 1250 MB for a pod holding realm caches and 10,000 sessions, of which about 300 MB is non-heap.
- CPU and acceleration
- Quiet at rest, sharp on login. The sizing guide budgets 1 vCPU per 15 password logins per second and 1 vCPU per 120 refresh token requests per second, and asks for 150 percent headroom for spikes. An unoptimized image also burns CPU re-augmenting itself on every boot.
- Storage growth
- Growth is in the database, not the container. Persistent user sessions became the default in 26.0, so sessions and revoked access tokens are written to Postgres; the sizing guide budgets 1400 write IOPS per 100 login, logout or refresh requests per second.
- Operational load
- 4 of 5, Heavy. Two services with a real database, a Liquibase schema migration on first start of every new version, and per-major migration notes you must read in order. 26.0 alone removed hostname v1, deleted the proxy option and cleared every cache on upgrade.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Everything is in PostgreSQL: realms, clients, users, credentials, sessions (persisted by default since 26.0) and revoked tokens. Back it up with pg_dump, and take that dump immediately before any version upgrade, because the schema migration runs automatically on first start of the new version and rolling the image tag back leaves an old jar facing a new schema. The container filesystem holds only what you baked in: custom providers in /opt/keycloak/providers, themes in /opt/keycloak/themes, and any keystore you supplied. Keep those in the image build, not in a volume. Realm exports from kc.sh export are good for moving configuration between environments but they are not a backup: they are not consistent with a live server and they omit credentials unless you ask.
Derived backup shape
Postgres dump. pg_dump (or pg_dumpall) into a file, then snapshot that file plus the app's data volume.
Traps and surprises#
start-dev is not a deployment
Development mode enables HTTP, disables strict hostname resolution and stores everything in a dev-file H2 database inside the container. People run it for months, then lose the realm to a docker compose down -v. There is no supported migration from H2 to PostgreSQL, so switching later means exporting realms and re-creating credentials. Configure the database on day one.
The 26.0 upgrade cliff
26.0 removed the hostname v1 feature, removed the proxy option in favor of proxy-headers plus proxy-trusted-addresses, switched Infinispan marshalling from JBoss Marshalling to Protostream (which clears every cache on upgrade), made persistent user sessions the default, and dropped the GELF log handler. Hostname v2 also rejects dots in the path. Read the whole 26.0 migration section even if you are coming from 25.
Build-time options versus run-time options
Database vendor, feature flags and some transaction settings are build-time options resolved by kc.sh build. Set them only as environment variables on an unoptimized image and Keycloak re-augments itself on every start, adding tens of seconds to boot. Set them on an image started with --optimized and they are ignored or rejected outright. Decide which image you are running before you debug why a flag did nothing.
Health and metrics moved off 8080
Since the management interface split, /health, /health/ready and /metrics are served on port 9000, not the main HTTP port. Container healthchecks and Kubernetes probes copied from older guides quietly fail, so the orchestrator restarts a perfectly healthy Keycloak in a loop. Point probes at 9000 and enable health and metrics explicitly, since they are off by default.
The schema migration is one-way
Liquibase migrates the database on first start of a new version, automatically, with no prompt. There is no reverse migration, so recovering from a bad upgrade means restoring the PostgreSQL dump you took beforehand, not changing the image tag back. On a large realm the migration can also exceed the default timeout; the upgrading guide documents both a timeout setting and a manual SQL export path for that case.
Specifications#
- Category
- Passwords, SSO and identity
- Licence
- Apache-2.0 (Permissive)
- Written in
- Java (Quarkus)
- First release
- 2014
- Maturity
- Mature
- Datastore
- PostgreSQL, MariaDB/MySQL, MSSQL or Oracle; a dev-file H2 database for development only
- Default ports
8080,8443,9000- Ships as
- docker, kubernetes operator, helm chart, zip distribution
- arm64 builds
- Yes
- Identity
- Native OIDC. Keycloak is the issuer, and it federates upward too: identity brokering to other OIDC and SAML providers, plus LDAP and Kerberos user federation with configurable write-back.
- Replaces
- Okta, Auth0, Microsoft Entra ID, Ping Identity
- Project site
- www.keycloak.org
- Source
- github.com/keycloak/keycloak
- Documentation
- www.keycloak.org/documentation
Alternatives to Keycloak#
Everything else in passwords, sso and identity, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| authentik | 4, Heavy | 1000 MB | MIT (core); authentik/enterprise/ under a separate Authentik Security license |
| Authelia | 3, Moderate | 35 MB | Apache-2.0 |
| Vaultwarden | 2, Light | 40 MB | AGPL-3.0 |
| LLDAP | 1, Set and forget | 15 MB | GPL-3.0 |
| Pocket ID | 1, Set and forget | 30 MB | BSD-2-Clause |
Where Keycloak comes up elsewhere#
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.