2026-04-21 self-host · SSO · OIDC · SAML · Keycloak · Authentik · Zitadel

Self-hosting SSO in 2026 —
a pragmatic guide.

Every identity platform vendor tells you that self-hosting is hard. They are not wrong, but they are also selling you something. Here is what self-hosting an identity platform actually costs in 2026, which open-source options are real contenders, and the specific operational traps you will hit in month three.

The honest reason you are reading this

You are almost certainly here because someone in a meeting brought up the Auth0 bill, or because a compliance question landed on your desk and "we are on third-party-hosted identity" was the wrong answer, or because your platform team wants to keep shipping product instead of negotiating Okta seat licences.

So: should you self-host?

Maybe. Probably not. Definitely not for the reasons you think.

When self-hosting is the right call

There are four genuinely good reasons to self-host an identity platform in 2026:

  • Regulatory or contractual data-residency constraints. POPIA, GDPR, HIPAA, PCI-DSS, or a customer that contractually forbids third-party-hosted auth. If the data literally cannot leave your infrastructure, self-host is not a choice; it is the constraint.
  • Your user volume makes managed cloud uneconomic. Above roughly 250 000 MAU, every per-MAU-priced vendor starts to look painful. Flat-rate vendors (FusionAuth, Stytch) remain reasonable; Auth0, Clerk and WorkOS do not. If you are at that scale and price-sensitive, self-host pays back in a year.
  • You genuinely have a platform team. If identity is a first-class concern for two or more engineers in your org, and those engineers enjoy operating backend infrastructure, the control you get from self-host compounds over time. Custom claim transforms, bespoke MFA flows, unusual federation patterns all get easier.
  • Your identity stack is a differentiator. If you are building a product in a regulated industry where identity is the product (banking, healthcare, government), you want to own the audit surface, the key material, and the upgrade cadence. Third-party hosting is a rough fit.

When self-hosting is the wrong call

The reasons people choose self-host that turn into regret within 18 months:

  • "It is free." It is not. The open-source licence is free. The engineering time to run it in production is not. More on this below.
  • "Auth0 is expensive." Yes, and the calculator at weldforge.org/calculator will tell you exactly how much you save vs Auth0 on a managed alternative that is not Auth0. Moving to Clerk or FusionAuth is almost always cheaper and faster than self-hosting.
  • "We need full control." Most teams that say this mean "we want the option to customise one specific thing." Almost every managed vendor supports that one specific thing via webhooks or custom claims. Ask them first.
  • "We will just run Keycloak in Kubernetes." Keycloak is real software and Kubernetes is a real platform. Neither of them solves the problems you are self-hosting to solve by themselves. You still need backup, monitoring, upgrade testing, TLS rotation, database sizing, Infinispan cache tuning, and someone to answer pages at 3am.

What self-hosting actually costs in 2026

Let us run the numbers for a typical mid-market workload: 25 000 monthly active users, two availability zones, Postgres backing store, 99.9% SLA target. 2026 prices.

Cost driver Year 1 (setup + ops) Year 2 onwards
Cloud infrastructure (2 × t3.medium + db.t4g.micro RDS + ALB + storage) ~$3 600 / yr ~$3 600 / yr
Engineering time — initial deployment + hardening ~3 weeks of 1 FTE = ~$17 000
Engineering time — ongoing ops (upgrades, monitoring, on-call) ~15% of 1 FTE = ~$30 000 ~15% of 1 FTE = ~$30 000
Engineering time — feature gaps you build yourself (SCIM SPIs, webhook plumbing, custom themes) ~4–10 weeks = ~$22–55 000 ~1 week / yr maintenance
Commercial support (optional) $3 000 – $18 000 / yr depending on vendor same
Total (first year, mid-estimate) ~$73 600 ~$37 000 / yr

Managed cloud equivalents for the same workload (25k MAU, 2026 list prices): Auth0 ~$13 200/yr, WeldForge Cloud Team ~$6 300/yr, Clerk ~$3 900/yr, FusionAuth Cloud Essentials ~$2 700/yr. The price delta is real. Before you self-host, you are deliberately choosing to pay 2–10× more per year for control you may not need.

The open-source options that are real contenders in 2026

Here is the honest field. None of these are bad software; they have different shapes and different audiences.

Keycloak

The default answer. Red Hat-backed, Apache 2.0, massive community, battle-tested in serious production. SAML and OIDC are first-class, user federation is comprehensive (LDAP, Kerberos, custom storage SPIs), the admin UI was recently replaced and is noticeably improved. You will run into three specific pain points over time:

  • Upgrade pain. The Quarkus migration broke custom themes and SPIs for a lot of teams. Major version jumps routinely require theme rewrites and occasionally data-model fixes. If your only Keycloak person leaves, the next upgrade becomes terrifying.
  • Missing things you will build. SCIM 2.0 is via community extensions. Internal PKI is not offered. HMAC-signed audit webhooks require an SPI. Your team will spend months building this infrastructure.
  • Memory footprint. Each Keycloak pod wants 1.5–2 GB minimum. With HA (2 pods) plus Infinispan cache and a Postgres backing, you are at 4 GB of RAM before any real load.

Still the right call for most mature platform teams. See the full Keycloak comparison.

Authentik

Newer, Python-based, more opinionated. Much cleaner admin UI than Keycloak ever was. Strong on OIDC + SAML, good MFA coverage (TOTP, WebAuthn, Duo, SMS). Community edition is unlimited and free.

  • Good fit if you like Django-shaped software and your team reads Python more comfortably than Java.
  • Smaller community than Keycloak — if you have a weird federation scenario, you are more likely to end up reading source code yourself.
  • SCIM is supported. PKI is not. Audit events are there but webhook export is DIY.

Zitadel

Rust + Go, event-sourced architecture, cloud-native-first. Probably the most modern of the pack. Good performance characteristics, solid multi-tenancy (they call it "instances" and "organizations"). Apache 2.0.

  • If you want event-sourcing semantics out of the box and your team appreciates that style of design, Zitadel is the pick.
  • Still maturing. Some edge-case protocol features (SAML encryption variants, exotic OIDC flows) lag Keycloak.
  • First-party cloud (zitadel.cloud) is a real option too — unusual for an OSS identity vendor.

Ory (Kratos / Hydra / Keto / Oathkeeper)

The power-user option. A set of composable services that together form an identity platform — Kratos for user management, Hydra for OAuth2 / OIDC, Keto for permissions, Oathkeeper for API gateway. Apache 2.0.

  • The composability is both the feature and the burden. If you want a full IdP you are running four services plus their data stores.
  • No admin UI out of the box — the implication is that you build one, or use Ory's commercial console.
  • Best fit for teams that want a build-it-yourself architecture with strong primitives. Worst fit for teams that want an out-of-the-box SSO.

FusionAuth Community Edition

Single Java binary, single Postgres, free for unlimited users on community tier. Strong on OIDC + SAML, passwordless magic-link flows are first class, themes are rich.

  • Not strictly open-source — community edition is free under a permissive EULA with specific usage restrictions. Most teams that do not care about OSS-vs-source-available also do not run into the EULA limits.
  • Flat-rate cloud tier is genuinely the price leader at scale. If you are self-hosting to save money at 100k+ MAU, check the cloud numbers first.
  • SCIM is Enterprise-tier only even for self-host.

WeldForge self-host (Developer tier)

Full disclosure: we make this one. Source-available, free for self-host evaluation and development. Spring Boot + Postgres + Angular admin console. Per-tenant OIDC issuer, SAML SP + IdP, SCIM 2.0, internal PKI, HMAC-signed audit webhooks, scoped API keys — all in the base binary, no extensions required.

  • Newer entrant than Keycloak. Fewer production deployments at the time of writing. If extreme maturity is a non-negotiable, Keycloak wins.
  • Has a first-party managed cloud option if you decide self-host is not worth it after all — smooth upgrade path.
  • POPIA-native data residency out of the box in Cape Town.

The operational traps you will hit

Independent of which platform you pick, these are the problems that bite every self-hosted IdP team somewhere around month three:

1. Signing-key rotation

JWT signing keys rotate on a schedule, and downstream clients cache the JWKS for minutes to hours. If you rotate without overlap (both old and new keys served in JWKS simultaneously), clients fail to verify valid tokens issued during the transition window. Every serious IdP supports key rotation with overlap; every self-hosted IdP team has broken production exactly once by forgetting the overlap flag.

2. Session invalidation on role change

User gets promoted to admin; the session JWT is still the old one with the old role. JWTs are stateless and cannot be revoked without a shared state. You need a token-version stored per user that the filter chain checks. Keycloak has "not-before policies" for this; most implementations you build yourself do not.

3. The break-glass account

When LDAP is unreachable because of a DNS failure, or Postgres fails over, or Keycloak itself crashes, you need a way in that does not depend on the broken system. A local admin account on a hardcoded backup path. Every mature IdP has one. Teams building their own usually forget until the incident.

4. Cache consistency across nodes

Your IdP runs multi-pod behind a load balancer. User logs in, hits pod A, gets a session. On the next request, load balancer sends them to pod B. Does pod B know about the session? Depends on your cache layer. Keycloak uses Infinispan; Authentik uses Redis; whatever you build yourself probably uses database polls until it falls over under load.

5. Password-hash migration

You migrated from Auth0 (bcrypt cost 10) to self-host. A year later you want to bump to bcrypt cost 12. Users who have not logged in since the migration still have their old hash. You cannot bulk rehash without knowing the plaintext. The solution is a lazy migration: on successful login, rehash and update the row. Most teams do not remember to do this and end up with a hash-cost fleet that takes years to fully migrate.

6. SAML metadata signature

Your IdP publishes SAML metadata at /saml2/idp/metadata. Downstream SPs (Okta, Azure AD, Salesforce) cache it. You rotate the signing cert; the metadata updates; the SPs do not refresh; every SSO login starts failing. Mature IdPs publish metadata with multiple signing certificates in parallel during rotation. Self-built ones rotate hard and break everything.

A minimal self-host stack that actually runs

If you are going to do this, here is the shape that works in practice:

# docker-compose.yml — the minimum viable self-hosted SSO
version: '3.8'
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: change_me
      POSTGRES_DB: sso
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s

  sso:
    image: <your-idp-image>
    environment:
      DB_URL: jdbc:postgresql://postgres:5432/sso
      DB_USER: postgres
      DB_PASS: change_me
      JWT_SECRET: <rotate-me>
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "8080:8080"

  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    ports:
      - "443:443"
    depends_on: [sso]

volumes:
  pgdata:

Anything less than this does not survive a restart. Anything massively more than this is probably overengineered. When you go to Kubernetes, the shape is the same — add a StatefulSet for Postgres, a Deployment for the IdP pods, a Service + Ingress, and cert-manager for TLS.

How to decide

A useful heuristic: count the number of engineers on your team who have shipped a production identity integration in the last two years. Multiply by two. If that number is at least one, you can self-host. If it is zero, you cannot.

Another useful heuristic: if the managed-cloud cost for your workload is under $10 000 per year, self-hosting is almost always the wrong answer. The ops time alone costs more than the subscription.

Above $50 000 per year on managed cloud, self-hosting starts to look interesting — but only if you have the team. Without the team, you end up with a half-operated production system and an identity story that is worse than what you left.

The portability question

Ask this before you commit to any platform — self-hosted or managed: if I want to leave you in two years, how does the data come out?

Good answers:

  • "We export everything as a standard SCIM dump plus password hashes in PHC format."
  • "Here is the Postgres schema. Dump it yourself."
  • "We support every standard wire protocol — if you change IdPs, your downstream apps do not change."

Bad answers:

  • "We have a proprietary export format."
  • "Passwords are hashed with our internal algorithm."
  • "Your integration uses our SDK, so you would need to rewrite."

Keycloak, Authentik, Zitadel, FusionAuth and WeldForge all give good answers here. Some commercial platforms give bad ones. Check before you sign.

What we would actually do if starting fresh

If someone asked us today: "we are 20 engineers, 15 000 MAU, one platform engineer, no special compliance constraints — what identity platform?"

The honest answer: pay Clerk or FusionAuth for the first two years. The managed-cloud cost is a rounding error compared to what your platform engineer's time is worth, and you will ship faster.

At 100 000 MAU, revisit. By then, you will know which features you actually use, which you wish you had, and which you never touched. Self-hosting at that point is an informed decision, not a cost optimisation based on spreadsheet projections.

Where WeldForge fits

We built WeldForge because the existing options had a specific shape we did not love: Auth0 was expensive, Keycloak was operationally heavy, Clerk was React-first, FusionAuth did not include SAML IdP emphasis or internal PKI. We wanted a platform where the base paid tier included every protocol enterprise buyers ask for, hosted in a region that satisfies POPIA natively, with an honest self-host option for teams that genuinely want one.

If that shape matches your problem, the pricing page explains the tiers and the deployment models page covers where it can run. The comparison index has honest head-to-head write-ups against the alternatives — including ones where we admit the other option wins.

And if the shape does not match, one of the six alternatives above almost certainly does. The point of this post was never to sell WeldForge; it was to help you self-host well if you go that route, or to help you decide honestly that you should not.

Discuss on Hacker News, r/selfhosted, or Dev.to. Corrections and follow-up questions to hello@weldforge.org.

Next up on the blog Writing a SAML IdP in Java with OpenSAML 4; the economics of multi-tenancy at the database layer; what we learned building a payment-gateway abstraction that picks the cheapest provider per transaction. Watch the blog index or the GitHub repo.