Authentik vs ClavionX: Python in the Policy Engine, and One Database for Everything

authentik's policies are Python run inside the server, and since 2025.10 it needs only Postgres. Expressiveness vs code-deploy rights, one store vs a ladder, and outposts.

Open an authentik admin console, create an expression policy, and you get a text box. What goes in the box is Python:

if request.user.group_attributes().get("contractor"):
    return request.http_request.META.get("REMOTE_ADDR", "").startswith("10.")
return True

That's a real access policy: contractors may only sign in from the internal network. It's readable and short, and it took a minute to write. The same text box also offers helper functions and a requests session, so the next policy someone writes could call an HTTP API in the middle of evaluating a login.

authentik is the most directly expressive platform in this series. Its policies, property mappings and flow logic are Python, executed by the server. It's also, as of late 2025, one of the simplest to run. Since release 2025.10, it needs nothing but PostgreSQL. Those two facts pull in opposite directions, and between them they make authentik the right place to finish a series about where identity platforms put their complexity.

Disclosure: I work on ClavionX. authentik is an excellent self-hosted identity provider with a large and loyal user base, and for many teams it's the better choice. The post says which.

What authentik actually is

authentik is an open-source identity provider written mainly in Python on Django, with protocol components in Go. The core is MIT licensed. An Enterprise edition adds features under a separate license, using the same images. It started as a favorite of self-hosters and has grown steadily into company use.

Its breadth is unusual:

  • OAuth 2.0/OIDC and SAML providers, plus LDAP and RADIUS providers, so applications and network gear that only speak those protocols can authenticate against it.
  • A proxy provider that puts authentication in front of applications with no native SSO support.
  • Sources: LDAP sync, SAML, OAuth and social logins, SCIM, Kerberos.
  • Flows and stages, which make authentication, enrollment and recovery sequences of configurable stages, with policies deciding which stages run.
  • Outposts, standalone Go services that implement the LDAP, RADIUS, proxy and remote-access protocols and talk to the core over its API.
  • Blueprints: YAML files that declare configuration, so an instance can be built and changed as code.

For an organization whose estate includes a NAS that only does LDAP, a VPN that only does RADIUS and an internal tool with no auth at all, authentik covers the lot. None of the other platforms in this series can say that as simply.

Python as the policy language

Most platforms in this series either refused to run customer code or confined it: sandboxed JavaScript with a timeout, or no I/O at all on the lower plans. authentik takes the most direct route. Expressions are Python evaluated inside the server, in expression policies that decide whether a flow or stage proceeds, and in property mappings that shape claims, SAML attributes, LDAP attributes and source imports.

This has real virtues. Python is a language operators already read. The expressions are short, local and visible in the admin UI and in blueprints. For the common case, such as "deny unless in this group", "set this claim from that attribute" or "only allow this network", it's hard to imagine anything more direct. It's also genuinely more capable than ClavionX's declarative attribute-to-claim mapping. That's a fair point in authentik's favor, not a caveat.

The questions it raises are the ones the extensibility argument predicts, sharpened by where the code runs:

  • Same process, same privileges. An expression runs with the server's access to its database, so to users, tokens and configuration. Who can author expressions is effectively a superuser question. Treat policy-edit rights in authentik the way you'd treat code-deploy rights to the identity server, because that's what they are.
  • I/O is available. The requests session makes a synchronous HTTP call one line away. The dependencies that line creates are the same as with every other callout in this series. Login latency tracks the remote service, availability multiplies, and a failure has to resolve to allow or deny. The difference is that no timeout or failure mode is set by a platform budget. It's whatever the expression author wrote.
  • Policies are code, whatever the UI calls them. They need review, tests and version control. Blueprints give you the last of those. The first two are a team discipline.

The practical guidance is the one that emerged in the FusionAuth comparison, and it applies directly. Expressions that compute are cheap and safe. Expressions that wait are dependencies. An authentik team can get most of the value with almost none of the risk by adopting one rule: no network calls in expressions on the login path. Push external data in through sources, SCIM or scheduled sync instead.

ClavionX sits at the far end of this. It has no expressions and no policy code, only a typed identity schema mapped to claims and attributes, with external data pushed in via SCIM. That's safer by construction, and it can't express the contractor rule above at all. ClavionX's network access policies are planned rather than built, which in practice means that rule would be enforced somewhere else today.

One database for everything

The second interesting decision is operational. Earlier authentik versions used PostgreSQL alongside Redis for caching, task queues and WebSocket connections. Over 2025, the project moved tasks and then caching and WebSockets into Postgres. With 2025.10, Redis was no longer needed at all. The release notes are frank that this uses noticeably more database connections.

That sits in direct tension with an argument this blog has made: most identity systems need at least four data stores, because configuration, ephemeral state, audit evidence and search have different access patterns, and co-locating them turns one workload's bad day into everyone's. Is authentik's consolidation a mistake?

Not for its deployment profile, and the reason is instructive. That post was explicit that one store is genuinely the right answer below a certain scale and operational maturity. Every extra store is a system to secure, back up, upgrade, monitor and understand at 3 a.m. For a team running identity for a few hundred or a few thousand people, a Redis that exists only to hold a task queue is pure operational cost. The failure mode it prevents, contention on a large, busy database, may simply never occur at that scale. Removing it is the right call for most authentik deployments. The cost is that growth eventually brings the contention back, and the escape route is capacity on the one database rather than a split.

ClavionX reaches the same conclusion from the other end. Its smallest deployment profile, Lite, needs nothing but Postgres and uses an in-process cache instead of Redis. Standard adds Redis for runtime state such as sessions. Large adds Kafka for event transport. Some parts of this profile model are still being completed. The architecture is explicitly layered so a deployment adds stores when its scale justifies them, rather than choosing once. authentik chose one store for everyone. ClavionX chose a ladder. At small scale, the two end up in the same place.

Outposts: a seam worth noticing

authentik's outposts deserve attention as a design, apart from their features. They're separate Go services that speak LDAP, RADIUS or reverse-proxy protocols to clients and talk to the authentik core over its API. They can be deployed close to the applications they serve, and they version in lockstep with the core.

That's the same instinct behind ClavionX's separation of control plane and runtime: put the protocol-facing workload in a separate process from the system of record, so each can be placed and scaled independently. The details differ. Outposts call the core's API and must run the same version as the server. ClavionX's runtime reads projected state and never calls the control plane during a request. In both, the identity system is split along the line between serving protocols and holding truth, which is where identity systems end up once they need to fail independently.

The capability difference is simple. ClavionX has no LDAP server interface, no RADIUS and no authenticating proxy. It speaks OIDC, OAuth 2.0, SAML and SCIM. It can verify passwords against an LDAP directory, but it can't be one. If your estate includes things that only speak LDAP or RADIUS, authentik covers them and ClavionX doesn't.

Tenancy and scale

authentik's configuration model is built around one organization. Brands let one instance present different domains and appearances, but the core model is a single directory with its applications, flows and policies. That fits authentik's primary use, identity for one organization's people and systems, very well.

ClavionX is built around the opposite primary use: one product serving many customer organizations. Each tenant has its own OIDC issuer, signing keys and policy, and applications can be declared global with a posture tenants can't loosen. If you're building a multi-tenant SaaS product, that structural difference matters more than any feature. If you're running identity for your own company, it barely matters at all.

When authentik is the better choice

Pick authentik when:

  • You're running identity for your own organization, especially a technical one, and want it self-hosted and open source.
  • Your estate is heterogeneous: LDAP-only devices, RADIUS for network access, legacy apps behind a proxy, alongside modern OIDC and SAML.
  • You want policy expressiveness and your team can treat expressions as reviewed, version-controlled code.
  • Operational simplicity is paramount, and a single Postgres dependency is exactly the right amount of infrastructure.
  • Configuration as code through blueprints fits how you work.

ClavionX fits better when you're building a multi-tenant product whose customers need their own issuers, keys and uniform posture. It also fits when you want no customer-authored code of any kind in the authentication process, and when the login-serving runtime must never wait on the system of record. As with every comparison in this series, weigh that against ClavionX's youth, its planned-but-unbuilt token exchange and adaptive policies, and a much smaller community.

The actual difference

authentik trusts its operators with a programming language and gives them one database to run. ClavionX trusts its operators with neither. It offers a declarative schema instead of code, and a ladder of data stores instead of one.

Both are coherent answers to different questions. authentik's question is how to give one organization's admins the most power with the least infrastructure. ClavionX's is how to give many customers' tenants guarantees that none of them can weaken. If you're answering the first question, authentik is one of the best tools there is. The one discipline worth borrowing from the other side is to keep the network out of your expressions.


Vendor details are from authentik's public documentation, release notes and repository as of September 2026. ClavionX capability status is taken from its public docs, ADRs and feature matrix. I work on ClavionX.