Keycloak vs ClavionX: When the Extension Model Is the Product
Keycloak made the extension model the product. What that costs at upgrade time, where its state lives, and when it beats a platform that runs no customer code.
The ticket is always titled something harmless. Upgrade Keycloak to current. It gets estimated at a sprint.
Then someone runs the new version against staging and the custom authenticator won't load. It was written three years ago to check a device-trust flag from an internal service before the OTP step. It compiles against interfaces that changed, and the engineer who wrote it has since moved teams. Nothing is wrong with Keycloak here. The upgrade ticket just happens to be the first time anyone has had to price the extension.
That ticket is the most honest place to start a comparison between Keycloak and ClavionX. It shows where each one decided to put the complexity, and that decision matters more than any feature list.
Disclosure up front: I work on ClavionX. I've tried to write this so it's useful to someone who picks Keycloak. For many teams that's the right call, and I say which ones below.
What Keycloak actually is
Keycloak is the most important open-source identity server there is. That's a statement of fact, not a courtesy. It's a CNCF project with Red Hat behind it and a commercially supported build. It covers OIDC, OAuth 2.0 and SAML 2.0 as both identity provider and broker, plus LDAP and Kerberos user federation, fine-grained authorization services, and a large admin console. Since the move to Quarkus it starts fast and runs happily in containers. It costs nothing to license, and it runs wherever you can run a JVM and a database.
It has also been hardened by a huge number of deployments whose operators write things down. When you search for a Keycloak error message, someone else has usually hit it and posted the fix. That kind of maturity can't be built in a year, and a younger platform shouldn't pretend otherwise.
So the interesting question isn't whether Keycloak is good. It's what kind of system Keycloak is, and whether that's the kind you want to operate.
The extension model is the product
Keycloak's defining design choice is the Service Provider Interface. Almost every behavior worth changing is a provider behind an SPI. That covers authenticators, required actions, user storage, protocol mappers, event listeners, themes, and even the storage of the storage. To change behavior, you write Java, package it as a JAR, drop it in providers/, and rebuild the server.
This is a real strength, and it explains why Keycloak shows up in so many places a hosted product can't reach. A bank can wire in its own risk engine, and a telco can authenticate against a subscriber database older than OAuth. If the thing is expressible in Java, Keycloak can be made to do it.
What matters is where that code runs:
flowchart LR
B["Browser"] --> KC
subgraph KC["Keycloak JVM"]
direction LR
F["Authentication flow"] --> CA["Your authenticator<br/>(your JAR)"]
CA --> M["Your protocol mapper<br/>(your JAR)"]
M --> S["Token signing"]
K[("Realm keys,<br/>sessions")]
end
CA -. "HTTP call" .-> R["Internal risk service"]
Your code runs in the same process as the realm's signing keys and the session cache, on the thread serving the login. If it makes a network call, the login waits. If it leaks memory, the node running every realm leaks memory. The argument from The Extensibility Trap applies here in full. It isn't a criticism of Keycloak specifically. It's the physics of any design that runs customer code in the auth path.
The part less often said aloud is about stability. Many of the SPIs people build on, the Authenticator SPI included, live in Keycloak's server-spi-private module. The project's stated compatibility policy guarantees backward compatibility only for features and APIs that are fully supported. That's a reasonable policy, and it's exactly what every extension point is a permanent public API predicts. The maintainers need the freedom to refactor internals. Their users have built on those internals because that's where the useful hooks are. Both sides are behaving rationally, and the cost lands on the upgrade ticket.
The practical lesson for a Keycloak team is to treat every custom provider as a product with an owner, a test suite that runs against the next Keycloak release, and an upgrade budget. Teams that do this upgrade smoothly. Teams that treat providers as one-off glue end up several major versions behind.
Where the state lives
The second thing that defines Keycloak operationally is its state.
For most of its history, Keycloak kept user sessions in Infinispan, a distributed in-memory cache embedded in the server. That made session reads fast. It also made cluster topology, cache ownership and cross-datacenter replication the part of Keycloak that operators actually had to understand. A rolling restart done wrong could drop sessions, which logs everyone out.
Keycloak 26 changed this in a direction worth studying. Persistent user sessions are now the default and part of the architecture. Sessions are written to the database and survive restarts and upgrades, and the cache sits in front of them rather than being the only copy. The internal marshalling also moved to Infinispan Protostream, which is designed for forward and backward compatibility.
The general lesson: a mature identity server, given enough years, moved its source of truth for sessions out of the cluster cache and into durable storage. That's the same conclusion argued from first principles in The Cost of Session Storage. It shows up again in any system whose operators have been paged enough times.
Realms, and what a tenant owns
Keycloak's unit of isolation is the realm. A realm owns its users, clients, roles, identity providers, keys and flows. It's clean, and it's easy to explain to an auditor: realm A can't see realm B.
The realm model gets harder when you're building B2B SaaS. You have one application and five hundred customer organizations, each with its own IdP and policies. The realm-per-customer pattern gives you strong isolation, but it also gives you five hundred copies of the same client definition. Those copies drift unless you automate them. Keycloak's answer is the Organizations feature, fully supported since Keycloak 26. It models customer organizations inside a single realm, with their own domains and brokered identity providers. It's a good addition, and anyone evaluating Keycloak for B2B should start there rather than with realm-per-tenant.
ClavionX took a different approach, recorded in its architecture decisions. The tenant is the security domain. A client or resource server is either scoped to one tenant or declared global and available to every tenant. Its security posture can't be overridden per tenant. That covers redirect URIs, grant types, PKCE requirements and token policy. Signing keys and the OIDC issuer are per-tenant.
The trade-off shows up as soon as a customer asks for something slightly different. In a realm, you edit that realm's client. In ClavionX, if two customers need different redirect URIs, they're two different applications, and the model says to register two clients. That's more rigid. In return, "has anyone weakened PKCE for one customer?" has a structural answer rather than one you have to audit for.
Neither model is correct in the abstract. Realms suit tenants that really are separate organizations with separate administrators. A canonical-client model suits one product serving many customers, where uniform posture is itself a requirement.
Configuration changes: immediate or projected
In Keycloak, the admin console and the login endpoints are the same server over the same database. Change a client, and the realm cache is invalidated across the cluster. The next login sees the change. Consistency is effectively immediate.
ClavionX splits these. The control plane owns configuration. The runtime that serves logins reads a projection of that configuration, delivered by events, and by design doesn't call the control plane during a request. There are two documented exceptions, for credential verification and signup. If the projected state it needs is missing, the runtime fails closed rather than guessing.
There are consequences both ways. With ClavionX, a control-plane outage doesn't stop logins, and admin traffic can't starve the login path. The cost is a consistency window: a change made in the console takes a short, bounded time to reach the runtime. Keycloak gives you immediacy and couples admin and runtime load on one fleet. If you've read What Should Identity Do When the Database Is Down?, you'll recognize this as the same trade-off made at a different layer.
Where ClavionX says no, and what it offers instead
ClavionX doesn't run customer code in the runtime. There's no provider JAR, no script mapper and no synchronous webhook. The alternatives are declarative:
- A tenant identity schema with custom attributes (string, number, boolean, date), mapped into OIDC claims and SAML attributes.
- Pre-synced data instead of fetch-at-login. The platform exposes a SCIM 2.0 endpoint for
/Users, so the source of truth pushes attributes ahead of time and login reads local state. - LDAP or Active Directory as a password authority, which ClavionX binds against to verify a password.
That last point is an honest exception to the principle, and it's worth stating. A password bind against a directory is a synchronous external call at login. It exists because a password you don't hold can't be pre-synced. The design contains the damage by having the directory answer only "is this credential correct?". Identity, MFA, sessions and groups stay local. That still makes it a dependency in the login path, and a slow domain controller will show up in your p99.
Compare it to Keycloak's LDAP user federation, which is considerably richer. It offers import and periodic sync, group and role mapping, Kerberos, and writable mode. If your directory integration is complex, Keycloak is simply ahead here.
Token exchange and agents: Keycloak is ahead
This section should be blunt, because it's the kind of thing vendor comparisons tend to hide.
Keycloak 26.2 made standard token exchange (RFC 8693) officially supported. The scope is exchange between clients within a realm. It added the JWT authorization grant and identity chaining later in the 26.x line. If you need delegation chains today, for services calling services on behalf of a user, Keycloak has shipped them.
In ClavionX, token exchange is planned, not built. The agent and MCP identity model is at the design stage. The intended model treats agents as registered objects with an owner and a lifecycle, compiles policy onto the underlying OAuth clients, and uses plain RFC 8693 for delegation. It may well be a good design, but it doesn't exist yet. If agent delegation is on your roadmap for this quarter, that settles the question.
When Keycloak is the better choice
Pick Keycloak when:
- You need a behavior only code can express, and you have the engineers to own that code. That includes custom authenticators, unusual user stores and bespoke protocol mappers. SPIs exist for exactly this.
- You want no vendor at all. An open-source project under a foundation, with a commercial support option if you want one, is a strong position for a long-lived system.
- Your directory integration is deep. You need LDAP sync, Kerberos/SPNEGO, or writable federation.
- You need token exchange or identity chaining now.
- You have a platform team that will treat identity as something it runs, with upgrade testing, cache topology knowledge and on-call.
ClavionX's constraints fit better when the requirement runs the other way. That means one product serving many customer tenants with uniform posture, a login path that must not depend on anything you don't control, and a team that would rather be told "not that way, here's how" than maintain a provider through every upgrade. It also means a team that can accept a younger platform with a shorter track record, whose delegation and agent features aren't shipped yet.
The actual difference
Keycloak's position is that the identity server should be able to do anything, and you decide what it does. ClavionX's position is that the identity server should do fewer things, which it can guarantee, and push everything else off the login path.
Both are coherent. The first makes the upgrade ticket expensive and a missing feature cheap. The second makes a missing feature expensive, sometimes impossible, and the upgrade ticket cheap. The useful question isn't which is better. It's which of those two bills your team is better placed to pay, and for how long.
Vendor details are from Keycloak's public documentation and release notes as of September 2026. ClavionX capability status is taken from its public docs and feature matrix; where something is planned or in design, I've said so. I work on ClavionX.