Keycloak vs Authentik vs Zitadel: Where Free Ends (2026)
Three self-hosted identity providers that all call themselves open source. The licence boundary sits in a different place in each one, and where it sits decides which you can actually use. Measured from the licence files, the container registries and the shipped config defaults.
On this page
Quick answer (2026)
If you need a self-hosted identity provider and you do not want a licence conversation later, run Keycloak. It is Apache-2.0 across the whole tree, one
LICENSE.txt at the root, and there is no directory anywhere in the repository carrying different terms. Every feature it has, you may run in production. The bill is paid in operational weight instead.
If you want the fastest thing to operate and you are comfortable reading a copyleft licence carefully, run Zitadel. We measured its published image at 50.7 MiB compressed across 3 layers, roughly a fifth of Keycloak, and it wants nothing but PostgreSQL. The core is AGPL-3.0-only, and the parts you actually write code against are deliberately not.
Run authentik when its administrative model fits how you think, and go in knowing that a named set of features sits behind a commercial licence that lives inside the same repository you cloned. That set is smaller and more specific than most write-ups suggest, and we corrected our own first reading of it below.
The three licences, read on September 4, 2026
Every comparison of these three calls all of them open source. That is true and it is not useful, because the licence boundary sits in a different place in each project, and where it sits is the thing that decides whether you can use it.
We read the licence files directly rather than the marketing pages.
Scroll to see more
| Project | GitHub reports | What the file actually says |
|---|---|---|
| Keycloak | Apache-2.0 | One LICENSE.txt, Apache-2.0, no carve-outs |
| authentik | NOASSERTION | MIT, with authentik/enterprise/ under a separate commercial licence |
| Zitadel | AGPL-3.0 | AGPL-3.0-only, with MIT and Apache-2.0 carve-outs |
The NOASSERTION on authentik is the interesting one. GitHub's licence detector returns that when it cannot classify a file, and here it cannot because authentik's LICENSE is a routing document. It assigns website/ to CC BY-SA 4.0, all client-side JavaScript to MIT Expat, anything under authentik/enterprise/ to a licence defined in that directory, and everything else to MIT.
That directory exists. It has its own LICENSE, and that file says the software it covers "may only be used in production, if you (and any entity that you represent) have agreed to, and are in compliance with, the Authentik Subscription Terms of Service". It also states that copying, merging, publishing, distributing, sublicensing and selling are forbidden, while explicitly permitting you to copy and modify the code for development and testing without a subscription.
Zitadel goes the other way and documents it plainly. Its LICENSING.md puts the server under AGPL-3.0-only, then carves out proto/ and apps/docs/ as Apache-2.0, and apps/login/, packages/zitadel-client/ and packages/zitadel-proto/ as MIT. Those three MIT paths are the login interface, the client library and the generated protobuf types, which is to say the exact surfaces you would fork, embed or import. The copyleft lands on the server you operate, not on the code you integrate against.
Zitadel is also unusually direct about the risk. Its own licensing policy says AGPL compliance "can be complex", recommends legal counsel, and points at commercial licensing for teams that do not want the obligation. It further requires all contributions to be Apache-2.0 so it can avoid a contributor licence agreement.
What authentik actually puts behind its enterprise licence
We listed the directory rather than guessing. As of September 4, 2026, authentik/enterprise/ contains:
- Providers:
google_workspace,microsoft_entra,radius,scim,ssf,ws_federation - Stages:
account_lockdown,authenticator_endpoint_gdtc,mtls,source - Policies:
unique_password - Plus:
endpoints/connectors,reports,requests,audit,agents
Read that list quickly and you reach an alarming conclusion: SCIM and RADIUS, two things a B2B buyer will ask for by name, appear to be paid features.
The correction, because our first reading was wrong
That conclusion is wrong, and we nearly published it.
There are two SCIM directories in the repository and two RADIUS directories. The ones outside authentik/enterprise/ are the substantial implementations. authentik/providers/scim carries clients/, models.py, tasks.py and its own migrations. authentik/providers/radius carries controllers/ and dictionaries/. Both are MIT.
The enterprise copies are thin. authentik/enterprise/providers/radius is three files. authentik/enterprise/providers/scim is a handful, and its app config gives the game away in one line:
class AuthentikEnterpriseProviderSCIMConfig(EnterpriseConfig):
name = "authentik.enterprise.providers.scim"
verbose_name = "authentik Enterprise.Providers.SCIM"
mountpoint = "application/scim/"
A mountpoint means authentik is serving a SCIM API. The MIT implementation has a clients/ directory, which means it is calling one. So the split is by direction, not by protocol:
- Outbound SCIM, where authentik pushes your users into a downstream application, is MIT and free.
- Inbound SCIM, where authentik exposes an endpoint that something else provisions into, is enterprise.
The same holds for RADIUS. The working provider is open source; the enterprise directory is a small extension on top.
So the honest version of the boundary is that authentik does not charge you for single sign-on. It charges for a cluster of directory-integration and governance features: Google Workspace and Microsoft Entra synchronisation, WS-Federation, Shared Signals, mutual TLS, approval workflows, reporting, audit middleware and account lockdown. For a lot of teams none of that is load-bearing. For a team selling into enterprises, several of them are exactly what procurement asks about.
Keycloak ships two of those free, with a real catch
Two items on authentik's enterprise list have Apache-2.0 counterparts sitting in Keycloak's tree: there is a scim module with client, core, model and services, and an ssf module with core, services and a transmitter.
The obvious headline is that Keycloak gives away what authentik sells. We checked before writing it, and the catch is in Keycloak's own feature registry, Profile.java:
SSF("Shared Signals Framework", Type.EXPERIMENTAL),
SCIM_API("Exposes a SCIM API for managing realm resources on a per-realm basis", Type.PREVIEW),
Neither is generally available. PREVIEW and EXPERIMENTAL are opt-in flags with no stability guarantee, and Keycloak has removed and reshaped preview features before. Note also that the SCIM description matches authentik's enterprise one almost exactly, both being a served API rather than an outbound client.
So the trade is not free versus paid. It is an unsupported implementation you may run without asking anyone, against a supported implementation with a licence attached. Which of those is cheaper depends entirely on whether the feature is on your critical path.
What each one costs you to run
Licences are one axis. We pulled the published images from their registries on September 4, 2026 and summed the compressed layers.
Scroll to see more
| Project | Image | Layers | Compressed |
|---|---|---|---|
| Zitadel | ghcr.io/zitadel/zitadel | 3 | 50.7 MiB |
| Keycloak | quay.io/keycloak/keycloak | 4 | 255.5 MiB |
| authentik | ghcr.io/goauthentik/server | 26 | 313.0 MiB |
The ordering surprised us. The received wisdom is that Keycloak is the heavy one because it runs on the JVM, but authentik, a Python application, ships a larger image across six times as many layers. Zitadel, a single Go binary, is roughly a fifth of either.
Runtime shape follows the same pattern, and two widely repeated facts about it are now out of date.
authentik no longer needs Redis. Its official docker-compose.yml defines exactly three services: postgresql, server and worker. We grepped it for Redis and found zero occurrences. Plenty of current write-ups still list Redis as a requirement.
Zitadel no longer needs CockroachDB. Its shipped cmd/defaults.yaml contains zero occurrences of cockroach, and the comment above the database block reads "Postgres is the default database of ZITADEL". Redis appears in that file only as an optional cache connector, and it is Enabled: false, with the Postgres cache enabled instead. One binary, one database.
One authentik detail is worth knowing before you deploy it rather than after. The official compose file runs the worker as user: root and bind-mounts /var/run/docker.sock into it. That is there so authentik can manage outpost containers, and you can remove both lines if you do not use that feature, but a container with the Docker socket is effectively root on the host, and this is your identity provider.
Where each one actually loses
Keycloak is the slowest to operate. It is the oldest of the three by six years, it carries the largest open issue count of the three, and its release train moves in larger, less frequent steps: a median of 13 days between the last ten stable releases, with gaps as wide as 33. Its cleanliness is real, but you pay for it in configuration surface.
authentik asks you to accept a commercial licence inside your source tree and to track which side of the line each feature sits on. That line is not visible in the admin interface at the moment you design a flow around a feature. It also has the largest deployment footprint of the three for the least obvious reason.
Zitadel puts AGPL-3.0-only on the server. For most teams running it unmodified as a separate service this is a much smaller problem than the internet suggests, but it is genuinely a question your legal function may want to answer, and Zitadel says so itself rather than waving it away. Its release cadence is also the fastest we measured, a median of 3 days across the last ten stable releases, with a v3 line still receiving patches alongside v4. Fast movement is a virtue until you are the one scheduling the upgrades.
What we did not measure
We did not benchmark authentication throughput, test any migration path between the three, or evaluate their administrative interfaces. We did not price any of the commercial tiers, deliberately: prices move, and a recommendation resting on one stops being true without warning. Everything above rests on licence text, directory structure, published images and shipped configuration defaults, all of which change slowly and visibly.
We also did not verify how each project enforces its licence at runtime. authentik ships a license.py and a public.pem in its enterprise directory, which is consistent with signed licence-key verification, but we did not run it unlicensed to see what degrades.
All three repositories were pushed to on the day we measured, and none is archived.
If you are choosing today
Start from where the boundary needs to be, not from a feature grid.
- You want no licence question at all, and can absorb the operations. Keycloak. Apache-2.0 end to end is a real and rare property, and it is the only one of the three where no future feature you enable can change your licensing position.
- You want the smallest thing that works, and copyleft on a standalone service is acceptable. Zitadel. The footprint difference is not marginal, and the MIT carve-outs land on precisely the code you would otherwise worry about.
- You like authentik's model and your requirements sit on the free side of its line. authentik. Check the list above against your roadmap first, particularly if directory synchronisation with Entra or Google Workspace is anywhere on it.
If you are earlier than this and still deciding whether to self-host an identity provider at all, the hosted comparison is a different question with different economics, and we covered the managed options in Clerk vs WorkOS vs Kinde and the library-level choices in Better Auth vs Auth.js vs Supabase Auth. Self-hosting an IdP is a decision about control and compliance, not about saving a subscription.
Sources we read directly
- authentik enterprise licence, read September 4, 2026
- Zitadel licensing policy, including the AGPL carve-outs
- Keycloak feature registry, where SCIM and SSF are marked preview and experimental
- authentik official compose file, for the service list and the worker configuration
Written by
Yui TanakaFrequently asked questions
Is authentik open source or not?
Both, and the split is documented in its own LICENSE file. The bulk of authentik is MIT. Everything under the authentik/enterprise/ directory carries a separate commercial licence that permits development and testing but requires a subscription for production use. As of September 4, 2026 that directory covers Google Workspace and Microsoft Entra sync, WS-Federation, Shared Signals, an mTLS stage, account lockdown, a unique-password policy, approval workflows, reporting, audit middleware and endpoint connectors.
Does authentik charge for SCIM?
Only in one direction, and this is easy to get wrong. Outbound SCIM, where authentik provisions your users into a downstream application, lives in authentik/providers/scim and is MIT licensed. The enterprise copy mounts a SCIM API at application/scim/, meaning authentik serves an endpoint that something else provisions into. Inbound is enterprise, outbound is free. RADIUS follows the same pattern, with the full provider open source and a small extension in the enterprise tree.
Does Zitadel's AGPL licence mean I have to open source my application?
Not on its own. Zitadel's server core is AGPL-3.0-only, and the obligation attaches to that program rather than to unrelated software that talks to it over a network. Running unmodified Zitadel as a separate service alongside your product is a very different situation from modifying Zitadel and offering the modified version. Zitadel's own licensing policy calls compliance complex, recommends legal counsel and offers commercial licensing, which is a fair summary. Note also that apps/login, packages/zitadel-client and packages/zitadel-proto are MIT, so the code you integrate against is not copyleft.
Which of the three is lightest to run?
Zitadel, by a wide margin. We summed the compressed layers published to each registry on September 4, 2026: Zitadel 50.7 MiB across 3 layers, Keycloak 255.5 MiB across 4, authentik 313.0 MiB across 26. Zitadel needs only PostgreSQL, and its shipped defaults now contain zero references to CockroachDB. authentik's official compose file runs three services, and despite many write-ups saying otherwise it no longer requires Redis.
Keycloak has SCIM and SSF built in, so why would I pay authentik for them?
Because Keycloak's are not generally available. Both modules are in the tree under Apache-2.0, but Keycloak's own feature registry marks SCIM_API as PREVIEW and SSF as EXPERIMENTAL. Those are opt-in flags with no stability guarantee. The real comparison is an unsupported implementation you may run freely against a supported one with a licence attached, and which is cheaper depends on whether the feature is on your critical path.
Is there anything to watch out for when deploying authentik?
Yes. The official docker-compose.yml runs the worker container as user root and bind-mounts /var/run/docker.sock into it. That exists so authentik can manage outpost containers, and you can remove both lines if you do not use that feature. A container holding the Docker socket is effectively root on the host, which deserves a deliberate decision when the container in question is your identity provider.
More from the garden
Clerk vs WorkOS vs Kinde: B2B SaaS authentication for Next.js (2026)
Clerk, WorkOS AuthKit, and Kinde are the three managed auth providers Next.js teams weigh in 2026. We compare how each charges (MRU vs MAU), their App Router SDKs, enterprise SSO cost, and where each one loses.
Better Auth vs Auth.js vs Supabase Auth: open-source authentication for a Next.js SaaS (2026)
A curator's take on the three open-source auth picks for a Next.js SaaS in 2026 (Better Auth, Auth.js, Supabase Auth), and the one axis that decides which shelf you pull from.
dnd-kit vs Pragmatic drag and drop vs react-beautiful-dnd for Next.js in 2026
Three React drag and drop libraries, three different stages of life. Read from the npm registry, the published tarballs and the GitHub API on 16 September 2026: one is archived, one is quietly split in two, and one is not a React library at all.