Bastionary vs Keycloak.
Self-hosted without the ops tax.
Keycloak is free, open-source, and remarkably full-featured. It's also a 500MB Java application that needs 2–4GB of RAM at idle, has an admin model and extension system steep enough to require a dedicated ops person, and an upgrade path that frequently requires planned migration work. Bastionary is self-hosted auth that fits on the same server as your app.
Keycloak is free. Keycloak ops is not.
- Memory requirements: Keycloak requires a minimum 512MB heap, with 1–2GB recommended in production. On a $6/mo server, that's most of your RAM.
- Startup time: Keycloak takes 30–90 seconds to start. Zero-downtime deploys require clustering. Clustering requires shared Infinispan or external cache. Your single Hetzner node suddenly needs three.
- Configuration model: Keycloak has a broad Admin REST API, but enterprise features like SAML IdP federation, custom user attribute providers, and SCIM often require SPI implementations, Freemarker template customization, JAR packaging, and navigating the admin console's multi-layer hierarchy. The API surface is real but the operational model is significantly more involved than a config-file-first or REST-first platform.
- Upgrade path: Keycloak major versions frequently break configuration. Upgrading from 20 to 24 is a documented multi-step migration with database schema changes. Most teams pin a version and fall behind on security patches.
- Customization cost: Custom login themes use Freemarker templates and optionally a JAR build for custom providers — but even basic theme changes require understanding Keycloak's template hierarchy. Bastionary's managed login pages are just CSS variables.
- No billing/licensing/flags: Keycloak does auth. You still need Stripe, Keygen, and LaunchDarkly. The five-vendor problem persists.
What each does out of the box.
| Feature | Keycloak | Bastionary |
|---|---|---|
| OIDC / OAuth 2.0 | ✓ Full | ✓ Full, RFC-compliant |
| SAML 2.0 | ✓ Full, XML-heavy config | ✓ Full, API-configured |
| SCIM 2.0 | ~ Third-party extension required | ✓ Built-in, no plugins |
| Memory footprint | ✗ 1–4GB JVM + heap | ✓ ~150MB Python process |
| Startup time | ✗ 30–90 seconds | ✓ Under 3 seconds |
| API-first configuration | ✗ Admin console or XML | ✓ Everything via REST API |
| Custom login themes | ~ Freemarker + JAR build | ✓ CSS variables, no rebuild |
| Billing integration | ✗ | ✓ Stripe, Paddle, LemonSqueezy |
| Software licensing | ✗ | ✓ Offline RSA keys, seat mgmt |
| Feature flags | ✗ | ✓ Built-in, plan-gated |
| HIBP breach detection | ✗ | ✓ Every password, k-anonymity (disableable for air-gapped deployments) |
| Tamper-evident audit log | ~ Event log, no chain | ✓ SHA-256 chained |
| DPoP tokens | ✗ | ✓ RFC 9449 |
| Zero-downtime upgrades | ✗ Requires cluster setup | ✓ Single process, no cluster needed |
| Cost | Free (pay with ops time) | $29–99/mo cloud, or self-hosted |
The honest recommendation.
Keycloak is the right choice if you need a free, deeply customizable IdP with an extensive plugin ecosystem, and you have an ops team with Java experience willing to maintain it. It handles extremely complex enterprise federation scenarios that few products match.
Bastionary is the right choice if you want self-hosted auth without the operational overhead, need billing + licensing + auth in one system, want an API-first configuration model, or are running on infrastructure where a 4GB Java process is a significant cost.
14-day free trial. Deploy anywhere.
Cloud Pro or self-hosted on your own server. One binary, standard OIDC, no JVM required.