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

KeycloakZitadel
LanguageJava (Quarkus)Go
LicenseApache 2.0AGPL-3.0 (v3+)
GitHub Stars41,000+13,000+
CNCF StatusIncubatingNot a CNCF project
First Release20142019
MaintainerRed HatCAOS AG (Switzerland)
ArchitectureStateful (Infinispan cache)Stateless (event-sourced)
DatabasePostgreSQL, MySQL, MariaDB, Oracle, MSSQLPostgreSQL only
Cloud OfferingRed 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.

[LoadBalancer][[KPeoysctlgoraekSQNLod/eM1y]SQL/[IMnafriinaiDsBp]an][KeycloakNode2]

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.

[LoadBalancer][[[ZZZiiitttaaadddeeelllPPPoooddd123]]][PostgreSQL]

Scaling means adding more pods behind a load balancer. No sticky sessions, no distributed cache, no JGroups. The operational simplicity is significant.

Resource Comparison

ResourceKeycloakZitadel
Minimum RAM512MB-1GB (JVM heap)256-512MB
Production RAM2-4GB per node512MB-1GB per node
Startup Time10-30 seconds1-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

ProtocolKeycloakZitadel
OAuth 2.0Full (all flows)Full (all flows)
OpenID ConnectCertifiedCertified
SAML 2.0Mature IdP and SPSupported, less battle-tested
LDAP FederationNative sync with attribute mappingLDAP via identity brokering only
Kerberos/SPNEGONativeNot supported
SCIM 2.0Community extensionsBuilt-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

FeatureKeycloakZitadel
RBACRealm roles, client roles, composite rolesProject roles with organization grants
Fine-Grained AuthorizationUMA 2.0, policy engine, resource-basedRBAC only; fine-grained requires external tools
Policy EngineBuilt-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

FeatureKeycloakZitadel
TOTPYesYes
WebAuthn/FIDO2SupportedFirst-class, passwordless-first
PasskeysSupported via WebAuthnNative, passwordless-first philosophy
SMS OTPVia SPI/extensionBuilt-in
Email OTPVia extensionBuilt-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

ApproachKeycloakZitadel
Extension ModelJava SPIs (compile JAR, deploy)Actions v2 (HTTP webhooks to any endpoint)
Custom AuthenticatorsJava classes implementing SPI interfacesHTTP endpoints called during auth flow
Event ListenersJava SPI-based listenersFire-and-forget HTTP webhooks
Custom ClaimsProtocol 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

APIKeycloakZitadel
RESTAdmin REST APIFull REST API (v1 stable, v2 beta)
gRPCNot supportedNative, API-first
TerraformOfficial 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

AspectKeycloakZitadel
Helm ChartCommunity charts (Bitnami, Codecentric)Official chart (charts.zitadel.com)
OperatorOfficial Keycloak Operator (CRDs for realm import)No operator; Helm-based
Sticky SessionsRequired (AUTH_SESSION_ID cookie)Not required (stateless)
HPACustom configurationBuilt-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.

KeycloakZitadel
LicenseApache 2.0AGPL-3.0 (v3+, May 2025)
SaaS ImplicationsNo restrictionsMust share modifications if running as a service
SDKs/LibrariesApache 2.0Apache 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

MetricKeycloakZitadel
GitHub Stars41,000+13,000+
Stack OverflowThousands of questionsMinimal
Community SizeMassive (CNCF, Discourse, Slack)Growing (Discord ~4,500 members)
Third-Party ContentExtensive tutorials, books, coursesGrowing blog and guide collection
Consulting/PartnersMany IAM consultants specialize in KeycloakSmaller 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

  1. Enterprise SAML requirements — Keycloak’s SAML implementation is battle-tested across thousands of enterprise deployments
  2. Active Directory / LDAP federation — Native sync with attribute mapping, group sync, and Kerberos. See the Keycloak LDAP Integration Guide
  3. Complex authorization policies — UMA 2.0, resource-based permissions, and built-in policy engine
  4. Apache 2.0 license needed — No copyleft restrictions for commercial SaaS use
  5. Largest community — Maximum ecosystem support, consultants, and third-party integrations
  6. Red Hat ecosystem — Seamless integration with OpenShift, RHEL, and Red Hat subscriptions
  7. CNCF governance — Prefer projects with neutral, vendor-independent governance

When to Choose Zitadel

  1. Multi-tenant SaaS — First-class organization support with per-tenant branding, IdPs, and delegated admin
  2. B2B identity — Built for managing customer organizations, each with their own users and policies
  3. Minimal operations — Single stateless binary, no Infinispan, no sticky sessions, lower resource requirements
  4. Passkeys-first — Passwordless-first design philosophy with strong FIDO2/WebAuthn support
  5. Language-agnostic extensions — Actions v2 HTTP webhooks instead of Java SPIs
  6. Event-sourced audit trail — Every identity change is an immutable event for compliance
  7. Managed cloud with free tier — Zitadel Cloud free tier (100 DAU) for startups and small teams
  8. 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.