Keycloak is the established open-source IAM platform with 41,000+ GitHub stars and CNCF backing. Zitadel is the challenger — a Go-based, event-sourced platform growing rapidly at 13,000+ stars. This comparison covers architecture, features, operations, and when each is the better choice.
At a Glance
| Keycloak | Zitadel | |
|---|---|---|
| Language | Java (Quarkus) | Go |
| License | Apache 2.0 | AGPL-3.0 (v3+) |
| GitHub Stars | 41,000+ | 13,000+ |
| CNCF Status | Incubating | Not a CNCF project |
| First Release | 2014 | 2019 |
| Maintainer | Red Hat | CAOS AG (Switzerland) |
| Architecture | Stateful (Infinispan cache) | Stateless (event-sourced) |
| Database | PostgreSQL, MySQL, MariaDB, Oracle, MSSQL | PostgreSQL only |
| Cloud Offering | Red Hat Build of Keycloak (subscription) | Zitadel Cloud (free tier: 100 DAU) |
Architecture
Keycloak
Keycloak runs on Java/Quarkus with Infinispan for distributed session caching. A production deployment requires Keycloak nodes + an external database + Infinispan cluster configuration. Nodes are stateful — they hold session data in memory, requiring sticky sessions for optimal performance.
Scaling requires configuring JGroups discovery, Infinispan cache sizes, and session affinity. Keycloak 26+ defaults to persistent sessions (database-backed), reducing cache eviction issues.
Zitadel
Zitadel is a single Go binary with no inter-node coordination. All state lives in PostgreSQL via event sourcing — every identity change is an immutable event. Application nodes are truly stateless.
Scaling means adding more pods behind a load balancer. No sticky sessions, no distributed cache, no JGroups. The operational simplicity is significant.
Resource Comparison
| Resource | Keycloak | Zitadel |
|---|---|---|
| Minimum RAM | 512MB-1GB (JVM heap) | 256-512MB |
| Production RAM | 2-4GB per node | 512MB-1GB per node |
| Startup Time | 10-30 seconds | 1-5 seconds |
| Container Image | ~400MB+ | ~100-200MB |
Zitadel’s Go binary requires significantly less memory than Keycloak’s JVM. For cost-sensitive deployments, this difference compounds across multiple nodes.
Feature Comparison
Authentication Protocols
| Protocol | Keycloak | Zitadel |
|---|---|---|
| OAuth 2.0 | Full (all flows) | Full (all flows) |
| OpenID Connect | Certified | Certified |
| SAML 2.0 | Mature IdP and SP | Supported, less battle-tested |
| LDAP Federation | Native sync with attribute mapping | LDAP via identity brokering only |
| Kerberos/SPNEGO | Native | Not supported |
| SCIM 2.0 | Community extensions | Built-in (preview) |
Keycloak wins for enterprises with legacy SAML applications and Active Directory environments. Its LDAP federation is a true sync engine with attribute mappers, not just authentication brokering.
Zitadel wins with built-in SCIM 2.0 for modern user provisioning scenarios.
Multi-Tenancy
This is the biggest differentiator.
Keycloak uses realms as tenant boundaries. Each realm is an isolated universe with its own users, clients, and configuration. This works but creates operational overhead:
- Each realm must be configured independently
- Hundreds of realms can cause performance degradation
- No built-in concept of “customer organization” within a realm
Zitadel has organizations as a first-class feature. An instance can host thousands of organizations, each with:
- Separate user pools
- Per-organization IdP configuration
- Per-organization login branding
- Delegated admin management
- Organization-level role grants
For a B2B SaaS product where each customer is a tenant, Zitadel’s architecture maps directly to the domain model. With Keycloak, you’d need to design a realm-per-tenant or realm-with-groups strategy.
Authorization
| Feature | Keycloak | Zitadel |
|---|---|---|
| RBAC | Realm roles, client roles, composite roles | Project roles with organization grants |
| Fine-Grained Authorization | UMA 2.0, policy engine, resource-based | RBAC only; fine-grained requires external tools |
| Policy Engine | Built-in (JavaScript, time-based, role-based) | No built-in policy engine |
Keycloak wins for complex authorization. Its Authorization Services provide UMA 2.0, resource-based permissions, and a policy evaluation engine. Zitadel’s RBAC is simpler but delegates fine-grained decisions to the application layer.
Passkeys and MFA
| Feature | Keycloak | Zitadel |
|---|---|---|
| TOTP | Yes | Yes |
| WebAuthn/FIDO2 | Supported | First-class, passwordless-first |
| Passkeys | Supported via WebAuthn | Native, passwordless-first philosophy |
| SMS OTP | Via SPI/extension | Built-in |
| Email OTP | Via extension | Built-in |
Zitadel wins for passkey-first authentication. Its design philosophy treats passwords as legacy, with passkeys as the primary credential. Keycloak supports passkeys but requires more configuration.
Extensibility
| Approach | Keycloak | Zitadel |
|---|---|---|
| Extension Model | Java SPIs (compile JAR, deploy) | Actions v2 (HTTP webhooks to any endpoint) |
| Custom Authenticators | Java classes implementing SPI interfaces | HTTP endpoints called during auth flow |
| Event Listeners | Java SPI-based listeners | Fire-and-forget HTTP webhooks |
| Custom Claims | Protocol mappers (Java or script-based) | Actions can add claims via HTTP |
Zitadel wins for developer experience. Actions v2 uses language-agnostic HTTP webhooks — extend Zitadel with any language or framework. Keycloak’s Java SPI model requires Java knowledge, JAR packaging, and redeployment.
Keycloak wins for depth of integration. SPIs can intercept and modify any part of the authentication pipeline at a level HTTP webhooks cannot match.
API
| API | Keycloak | Zitadel |
|---|---|---|
| REST | Admin REST API | Full REST API (v1 stable, v2 beta) |
| gRPC | Not supported | Native, API-first |
| Terraform | Official provider (v5+) | Official provider |
Zitadel’s gRPC-first design offers better performance for high-throughput API integrations.
Deployment
Docker Compose
Keycloak:
services:
keycloak:
image: quay.io/keycloak/keycloak:26.5
command: start-dev
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: password
KC_HOSTNAME: localhost
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
ports:
- "8080:8080"
depends_on:
- postgres
postgres:
image: postgres:16
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
Zitadel:
services:
zitadel:
image: ghcr.io/zitadel/zitadel:latest
command: start-from-init --masterkey "MasterkeyNeedsToHave32Characters"
environment:
ZITADEL_DATABASE_POSTGRES_HOST: postgres
ZITADEL_DATABASE_POSTGRES_PORT: 5432
ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: password
ZITADEL_EXTERNALDOMAIN: localhost
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: admin@localhost
ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: Password1!
ports:
- "8080:8080"
depends_on:
- postgres
postgres:
image: postgres:16
environment:
POSTGRES_DB: zitadel
POSTGRES_USER: zitadel
POSTGRES_PASSWORD: password
Both require PostgreSQL. The setup complexity is comparable for development environments.
Kubernetes
| Aspect | Keycloak | Zitadel |
|---|---|---|
| Helm Chart | Community charts (Bitnami, Codecentric) | Official chart (charts.zitadel.com) |
| Operator | Official Keycloak Operator (CRDs for realm import) | No operator; Helm-based |
| Sticky Sessions | Required (AUTH_SESSION_ID cookie) | Not required (stateless) |
| HPA | Custom configuration | Built-in HPA support in Helm chart |
Zitadel’s stateless architecture makes Kubernetes deployment simpler — no sticky sessions, no distributed cache coordination.
Licensing
This is a critical difference for commercial use.
| Keycloak | Zitadel | |
|---|---|---|
| License | Apache 2.0 | AGPL-3.0 (v3+, May 2025) |
| SaaS Implications | No restrictions | Must share modifications if running as a service |
| SDKs/Libraries | Apache 2.0 | Apache 2.0 (SDKs only) |
Keycloak’s Apache 2.0 license has no copyleft restrictions — you can modify and deploy it in any context without sharing your changes. Zitadel’s AGPL-3.0 (since v3.0) requires sharing modifications if you offer Zitadel as a service. This matters for companies building IAM into their SaaS products.
Community and Ecosystem
| Metric | Keycloak | Zitadel |
|---|---|---|
| GitHub Stars | 41,000+ | 13,000+ |
| Stack Overflow | Thousands of questions | Minimal |
| Community Size | Massive (CNCF, Discourse, Slack) | Growing (Discord ~4,500 members) |
| Third-Party Content | Extensive tutorials, books, courses | Growing blog and guide collection |
| Consulting/Partners | Many IAM consultants specialize in Keycloak | Smaller partner ecosystem |
Keycloak’s maturity means you’ll find answers to almost any question on Stack Overflow or the Keycloak Discourse forum. With Zitadel, you’ll rely more on official docs and GitHub Discussions.
When to Choose Keycloak
- Enterprise SAML requirements — Keycloak’s SAML implementation is battle-tested across thousands of enterprise deployments
- Active Directory / LDAP federation — Native sync with attribute mapping, group sync, and Kerberos. See the Keycloak LDAP Integration Guide
- Complex authorization policies — UMA 2.0, resource-based permissions, and built-in policy engine
- Apache 2.0 license needed — No copyleft restrictions for commercial SaaS use
- Largest community — Maximum ecosystem support, consultants, and third-party integrations
- Red Hat ecosystem — Seamless integration with OpenShift, RHEL, and Red Hat subscriptions
- CNCF governance — Prefer projects with neutral, vendor-independent governance
When to Choose Zitadel
- Multi-tenant SaaS — First-class organization support with per-tenant branding, IdPs, and delegated admin
- B2B identity — Built for managing customer organizations, each with their own users and policies
- Minimal operations — Single stateless binary, no Infinispan, no sticky sessions, lower resource requirements
- Passkeys-first — Passwordless-first design philosophy with strong FIDO2/WebAuthn support
- Language-agnostic extensions — Actions v2 HTTP webhooks instead of Java SPIs
- Event-sourced audit trail — Every identity change is an immutable event for compliance
- Managed cloud with free tier — Zitadel Cloud free tier (100 DAU) for startups and small teams
- gRPC API — Native gRPC for high-performance API integrations
Migration: Keycloak to Zitadel
Zitadel provides an official migration CLI:
zitadel-tools migrate keycloak --realm-export realm-export.json
What migrates:
- Users with pbkdf2 password hashes
- Organizations mapped from realms
- Basic user attributes
What requires manual work:
- bcrypt passwords (users must re-enroll)
- SAML client configurations
- Java SPIs → Actions v2 HTTP endpoints
- FreeMarker themes → Zitadel branding API
- Keycloak-specific token mappers → Zitadel Actions
For large migrations (10,000+ users), plan for batched imports of ~5,000 users per batch.
