Project Overview
Ory Hydra is a production-grade OAuth2.1 and OpenID Connect (OIDC) authorization server written in Go. It handles token issuance, consent flows, and client credential verification — the authorization server side of OAuth2. What it deliberately does not do is manage users, passwords, or login forms.
You deploy Hydra alongside your existing user management system. When a user needs to authenticate, Hydra redirects to a consent app you build, which authenticates the user against your database and signals back to Hydra. Hydra then issues the tokens. Your user data stays in your schema.
Hydra is OpenID Certified™ for multiple profiles including Basic OP and Implicit OP. You can run it as a managed service on Ory Network or self-host it via Docker or Kubernetes. The project is under active commercial-backed development.
Key Challenges Addressed
Implementing OAuth2 from scratch is dangerous. The OAuth2 and OIDC specifications span dozens of RFCs. Token issuance, PKCE, scope validation, and refresh token rotation each have spec-defined edge cases that are easy to get wrong. Hydra gives you a certified implementation instead.
Scaling token validation under load. Hydra's public API is stateless for JWT-based tokens — resource servers verify locally using Hydra's JWKS endpoint. At high request volume, you avoid centralized token validation becoming a bottleneck.
OIDC certification requirements. If customers or procurement processes require OpenID Certified™ integration, Hydra satisfies that requirement. A custom OAuth2 implementation does not.
Decoupling user management from the authorization server. Monolithic auth systems store your user data inside their system. Hydra calls out to your existing user store. You own the schema, the password hashing algorithm, and the migration path.
Getting Started
Hydra is distributed as a single Go binary and as a Docker image. The fastest local path uses the provided Docker Compose quickstart:
git clone https://github.com/ory/hydra.git
cd hydra
docker-compose -f quickstart.yml up --build
For a real deployment, point Hydra at PostgreSQL and run the migration before starting the server:
hydra migrate sql --yes postgres://hydra:secret@postgres:5432/hydra?sslmode=disable
Sharp edges you will hit immediately:
- Without a consent app, no user authentication is possible. Hydra has no built-in login UI. Before any OAuth2 flow works end-to-end, you need a running consent redirect service. The hydra-login-consent-node example is the fastest starting point.
SECRETS_SYSTEMmust be set before first run and must never change without a deliberate migration. Changing it silently invalidates all existing sessions.- If you misconfigure the consent redirect URL, Hydra returns a generic
redirect_uri_mismatcherror with no indication of which client's configuration is wrong. Check/admin/clientsfirst before debugging the consent flow.
Features and Use Cases
Full OAuth2.1 and OIDC server. Hydra implements authorization code flow with PKCE enforcement, client credentials, refresh tokens, token introspection, token revocation, and the device authorization grant. You issue JWTs or opaque tokens depending on your revocation requirements.
Multi-tenant client management. Each OAuth2 client gets its own allowed scopes, redirect URIs, grant types, and token lifetime configuration, all managed via the admin API. This is the mechanism for exposing your API to third-party developers: each developer registers as a client.
Consent and session management. Hydra manages the consent challenge lifecycle — redirecting users to your consent app, waiting for your accept/reject call to the admin API, and issuing tokens or error responses accordingly. Sessions persist across browser restarts and can be invalidated at the Hydra level independently of your application's session store.
Realistic scenario: first-party mobile app. Your iOS app uses PKCE-based authorization code flow. Users authenticate through your existing login screen (the consent app). Hydra issues short-lived access tokens and rotating refresh tokens. Your API validates them against Hydra's JWKS endpoint. You control the UX, the user database, and the token lifetimes.
Realistic scenario: third-party developer API. You're opening your platform to external integrations. Each developer registers an OAuth2 client with scoped permissions. Hydra handles token issuance, rotation, and introspection without exposing your user data to developers or modifying your existing user service.
Ecosystem and Dependencies
Hydra integrates with the rest of the Ory stack:
- Ory Kratos handles user identity — registration, login, MFA, and password reset. You wire Kratos as the backend for your Hydra consent app. Together they form a complete IAM stack where Kratos owns identity and Hydra owns authorization.
- Ory Oathkeeper is an identity-aware reverse proxy. It validates Hydra-issued tokens at the network edge and injects identity headers into upstream requests. Useful for service-mesh authorization without modifying each service.
- Ory Keto adds relationship-based access control (ReBAC) — Google Zanzibar-style permissions. Hydra handles "who are you?"; Keto handles "what can you do and on which resource?"
Hydra ships OpenAPI-generated SDKs for Go, JavaScript/TypeScript, Python, PHP, Java, and Ruby. The Go SDK is first-class and used in Hydra's own integration tests.
Database support covers PostgreSQL, MySQL, SQLite, and CockroachDB. Use PostgreSQL in production. SQLite is for local development only — do not use it under concurrent write load.
Architectural Overview
Hydra exposes two separate HTTP APIs:
- Public API (default port
4444): Internet-facing. Handles/oauth2/auth,/oauth2/token,/userinfo,.well-known/openid-configuration, and the JWKS endpoint. - Admin API (default port
4445): Internal-only. Used by your consent app and operational tooling. Never expose this to the public internet.
In production, your load balancer or ingress routes port 4444 externally and blocks port 4445 at the network boundary. This is not enforced by Hydra itself — it is your operational responsibility.
State lives in the relational database. Hydra is itself stateless: you scale horizontally by running multiple Hydra instances against the same PostgreSQL database. There is no distributed cache to manage.
The consent flow sequence:
- Your client app redirects the user to Hydra's
/oauth2/auth. - Hydra redirects to your consent app with a
login_challengetoken. - Your consent app authenticates the user and calls Hydra's admin API to accept the challenge with the user's subject identifier and claims.
- Hydra redirects to the client's
redirect_uriwith an authorization code. - The client exchanges the code for tokens at
/oauth2/token.
JWT access tokens are validated without a Hydra call — resource servers fetch the JWKS once and verify signatures locally. Opaque tokens require a call to Hydra's introspection endpoint on every validation, which hits the database. Choose based on your revocation requirements.
Pros and Cons
Pros
- OpenID Certified™ for multiple profiles — satisfies procurement and compliance requirements without additional audit work.
- Headless design — your user data stays in your schema, not Hydra's database.
- Go runtime handles high concurrency with low memory footprint versus JVM-based alternatives.
- Horizontally scalable with no distributed cache dependency.
- Active development with commercial backing and a managed cloud option at Ory Network.
- Full OAuth2.1 support including PKCE enforcement, device authorization grant, and token revocation.
Cons
- The consent app is mandatory and must be implemented before any end-to-end flow works. For teams new to OAuth2, this is real upfront work.
- JWT access tokens cannot be revoked before expiry — immediate revocation requires opaque tokens, which add a network round-trip per resource server validation call.
- Self-hosting requires operational ownership of the database, the binary, the consent app, and the admin API network boundary.
- No built-in user management. You need an existing user store or a companion service like Ory Kratos before Hydra is useful.
- Configuration surface is large. Interaction effects between PKCE enforcement settings, token lifetime configuration, and cookie security flags require careful reading of the Ory Hydra documentation.
Comparison and Alternatives
GitHub stars
Weekly star gains
Full metrics details
GitHub GraphQL current stargazer cohort, reconstructed from starredAt events and totalCount retrieved in one stable pagination walk. GitHub does not expose historical unstar events, so this is not an exact ledger of past star counts.
Hydra
GitHub GraphQL current stargazer cohort, reconstructed from starredAt events and totalCount retrieved in one stable pagination walk. GitHub does not expose historical unstar events, so this is not an exact ledger of past star counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub GraphQL current stargazer cohort, reconstructed from starredAt events and totalCount retrieved in one stable pagination walk. GitHub does not expose historical unstar events, so this is not an exact ledger of past star counts.
164 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub GraphQL current stargazer cohort, reconstructed from starredAt events and totalCount retrieved in one stable pagination walk. GitHub does not expose historical unstar events, so this is not an exact ledger of past star counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub GraphQL current stargazer cohort, reconstructed from starredAt events and totalCount retrieved in one stable pagination walk. GitHub does not expose historical unstar events, so this is not an exact ledger of past star counts.
175 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub GraphQL current stargazer cohort, reconstructed from starredAt events and totalCount retrieved in one stable pagination walk. GitHub does not expose historical unstar events, so this is not an exact ledger of past star counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Issues opened
Weekly total
Full metrics details
GitHub API observation. Historical values render only when the source provides a real observation for that day.
Hydra
GitHub API observation. Historical values render only when the source provides a real observation for that day.
131 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Issues closed
Weekly total
Full metrics details
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
Hydra
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
131 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Pull requests opened
Weekly total
Full metrics details
GitHub API observation. Historical values render only when the source provides a real observation for that day.
Hydra
GitHub API observation. Historical values render only when the source provides a real observation for that day.
131 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Pull requests closed
Weekly total
Full metrics details
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
Hydra
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
131 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Pull requests merged
Weekly total
Full metrics details
GitHub API observation. Historical values render only when the source provides a real observation for that day.
Hydra
GitHub API observation. Historical values render only when the source provides a real observation for that day.
131 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub API observation. Historical values render only when the source provides a real observation for that day.
143 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Open/closed pull request ratio
Weekly average
Full metrics details
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
Hydra
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
164 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
175 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub Search pull-request totals queried for exact UTC days; rolling values are sums of proven daily counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Open/closed issues ratio
Weekly average
Full metrics details
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
Hydra
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
164 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
175 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub Search issue totals queried for exact UTC days; rolling values are sums of proven daily counts.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Releases
Weekly total
Full metrics details
GitHub release published_at events bucketed by UTC day; drafts are excluded.
Hydra
GitHub release published_at events bucketed by UTC day; drafts are excluded.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Keycloak
GitHub release published_at events bucketed by UTC day; drafts are excluded.
164 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Dex
GitHub release published_at events bucketed by UTC day; drafts are excluded.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Zitadel
GitHub release published_at events bucketed by UTC day; drafts are excluded.
175 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
node-oidc-provider
GitHub release published_at events bucketed by UTC day; drafts are excluded.
180 observed daily rows. Missing days are not fabricated.
| Date | Value |
|---|
Hotness score
Weekly average
Full metrics details
Derived only from GitHub GraphQL starredAt events after daily star totals are reconciled.
Hydra
Derived only from GitHub GraphQL starredAt events after daily star totals are reconciled.
180 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.40 × Hot today + 0.40 × Hot week + 0.20 × Breakout.
- Same-day multiplier = stars 1d ÷ max(1, stars 7d ÷ 7)
- Weekly multiplier = stars 7d ÷ max(1, stars 30d ÷ 30 × 7)
- Fortnight multiplier = stars 14d ÷ max(1, stars 90d ÷ 90 × 14)
- Hot today = clamp(70 × log-scale(stars 1d, 1000) + 30 × breakout-scale(same-day, 4))
- Hot week = clamp(75 × log-scale(stars 7d, 5000) + 25 × breakout-scale(weekly, 3))
- Breakout = clamp(35 × breakout-scale(same-day, 4) + 40 × breakout-scale(weekly, 3) + 25 × breakout-scale(fortnight, 2.5))
| Date | Stars | Stars 1d | Stars 7d | Stars 14d | Stars 30d | Stars 90d | Same-day multiplier | Weekly multiplier | Fortnight multiplier | Hot today | Hot week | Breakout | Stored score |
|---|
Keycloak
Derived only from GitHub GraphQL starredAt events after daily star totals are reconciled.
164 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.40 × Hot today + 0.40 × Hot week + 0.20 × Breakout.
- Same-day multiplier = stars 1d ÷ max(1, stars 7d ÷ 7)
- Weekly multiplier = stars 7d ÷ max(1, stars 30d ÷ 30 × 7)
- Fortnight multiplier = stars 14d ÷ max(1, stars 90d ÷ 90 × 14)
- Hot today = clamp(70 × log-scale(stars 1d, 1000) + 30 × breakout-scale(same-day, 4))
- Hot week = clamp(75 × log-scale(stars 7d, 5000) + 25 × breakout-scale(weekly, 3))
- Breakout = clamp(35 × breakout-scale(same-day, 4) + 40 × breakout-scale(weekly, 3) + 25 × breakout-scale(fortnight, 2.5))
| Date | Stars | Stars 1d | Stars 7d | Stars 14d | Stars 30d | Stars 90d | Same-day multiplier | Weekly multiplier | Fortnight multiplier | Hot today | Hot week | Breakout | Stored score |
|---|
Dex
Derived only from GitHub GraphQL starredAt events after daily star totals are reconciled.
180 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.40 × Hot today + 0.40 × Hot week + 0.20 × Breakout.
- Same-day multiplier = stars 1d ÷ max(1, stars 7d ÷ 7)
- Weekly multiplier = stars 7d ÷ max(1, stars 30d ÷ 30 × 7)
- Fortnight multiplier = stars 14d ÷ max(1, stars 90d ÷ 90 × 14)
- Hot today = clamp(70 × log-scale(stars 1d, 1000) + 30 × breakout-scale(same-day, 4))
- Hot week = clamp(75 × log-scale(stars 7d, 5000) + 25 × breakout-scale(weekly, 3))
- Breakout = clamp(35 × breakout-scale(same-day, 4) + 40 × breakout-scale(weekly, 3) + 25 × breakout-scale(fortnight, 2.5))
| Date | Stars | Stars 1d | Stars 7d | Stars 14d | Stars 30d | Stars 90d | Same-day multiplier | Weekly multiplier | Fortnight multiplier | Hot today | Hot week | Breakout | Stored score |
|---|
Zitadel
Derived only from GitHub GraphQL starredAt events after daily star totals are reconciled.
175 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.40 × Hot today + 0.40 × Hot week + 0.20 × Breakout.
- Same-day multiplier = stars 1d ÷ max(1, stars 7d ÷ 7)
- Weekly multiplier = stars 7d ÷ max(1, stars 30d ÷ 30 × 7)
- Fortnight multiplier = stars 14d ÷ max(1, stars 90d ÷ 90 × 14)
- Hot today = clamp(70 × log-scale(stars 1d, 1000) + 30 × breakout-scale(same-day, 4))
- Hot week = clamp(75 × log-scale(stars 7d, 5000) + 25 × breakout-scale(weekly, 3))
- Breakout = clamp(35 × breakout-scale(same-day, 4) + 40 × breakout-scale(weekly, 3) + 25 × breakout-scale(fortnight, 2.5))
| Date | Stars | Stars 1d | Stars 7d | Stars 14d | Stars 30d | Stars 90d | Same-day multiplier | Weekly multiplier | Fortnight multiplier | Hot today | Hot week | Breakout | Stored score |
|---|
node-oidc-provider
Derived only from GitHub GraphQL starredAt events after daily star totals are reconciled.
180 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.40 × Hot today + 0.40 × Hot week + 0.20 × Breakout.
- Same-day multiplier = stars 1d ÷ max(1, stars 7d ÷ 7)
- Weekly multiplier = stars 7d ÷ max(1, stars 30d ÷ 30 × 7)
- Fortnight multiplier = stars 14d ÷ max(1, stars 90d ÷ 90 × 14)
- Hot today = clamp(70 × log-scale(stars 1d, 1000) + 30 × breakout-scale(same-day, 4))
- Hot week = clamp(75 × log-scale(stars 7d, 5000) + 25 × breakout-scale(weekly, 3))
- Breakout = clamp(35 × breakout-scale(same-day, 4) + 40 × breakout-scale(weekly, 3) + 25 × breakout-scale(fortnight, 2.5))
| Date | Stars | Stars 1d | Stars 7d | Stars 14d | Stars 30d | Stars 90d | Same-day multiplier | Weekly multiplier | Fortnight multiplier | Hot today | Hot week | Breakout | Stored score |
|---|
Reliability score
Weekly average
Full metrics details
Derived from the displayed continuity, closure, shipping, liveness, and support-burden components.
Hydra
Derived from the displayed continuity, closure, shipping, liveness, and support-burden components.
180 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.30 × Continuity + 0.30 × Closure + 0.20 × Shipping + 0.10 × Liveness + 0.10 × Support burden.
- Continuity = 35% active ratio 90d + 20% active ratio 30d + 15% PR efficiency 90d + 10% PR efficiency 30d + 10% liveness + 10% observed-history coverage
- Closure = 55% PR merge efficiency 90d + 45% issue close efficiency 90d
- Shipping = 100 × (20% × release ratio 30d + 30% × release ratio 90d + 50% × release ratio 180d); ratios are releases ÷ 2, 6, and 12, capped at 1
- Support burden = 100 − 2 × open issues per 1,000 stars
- Liveness = 100 × exp(−pushed days ago ÷ 120)
Stars, issues, pull requests, and releases are daily observations. Pushed-days and license are repository snapshot-derived inputs and are not independent historical GitHub events.
| Date | Issues opened | Issues closed | PRs opened | PRs merged | Releases | Stars | Open issues | Pushed days ago | Continuity | Closure | Shipping | Liveness | Support burden | License | Observed days | Missing days | Needs healing | Stored score |
|---|
Keycloak
Derived from the displayed continuity, closure, shipping, liveness, and support-burden components.
164 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.30 × Continuity + 0.30 × Closure + 0.20 × Shipping + 0.10 × Liveness + 0.10 × Support burden.
- Continuity = 35% active ratio 90d + 20% active ratio 30d + 15% PR efficiency 90d + 10% PR efficiency 30d + 10% liveness + 10% observed-history coverage
- Closure = 55% PR merge efficiency 90d + 45% issue close efficiency 90d
- Shipping = 100 × (20% × release ratio 30d + 30% × release ratio 90d + 50% × release ratio 180d); ratios are releases ÷ 2, 6, and 12, capped at 1
- Support burden = 100 − 2 × open issues per 1,000 stars
- Liveness = 100 × exp(−pushed days ago ÷ 120)
Stars, issues, pull requests, and releases are daily observations. Pushed-days and license are repository snapshot-derived inputs and are not independent historical GitHub events.
| Date | Issues opened | Issues closed | PRs opened | PRs merged | Releases | Stars | Open issues | Pushed days ago | Continuity | Closure | Shipping | Liveness | Support burden | License | Observed days | Missing days | Needs healing | Stored score |
|---|
Dex
Derived from the displayed continuity, closure, shipping, liveness, and support-burden components.
180 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.30 × Continuity + 0.30 × Closure + 0.20 × Shipping + 0.10 × Liveness + 0.10 × Support burden.
- Continuity = 35% active ratio 90d + 20% active ratio 30d + 15% PR efficiency 90d + 10% PR efficiency 30d + 10% liveness + 10% observed-history coverage
- Closure = 55% PR merge efficiency 90d + 45% issue close efficiency 90d
- Shipping = 100 × (20% × release ratio 30d + 30% × release ratio 90d + 50% × release ratio 180d); ratios are releases ÷ 2, 6, and 12, capped at 1
- Support burden = 100 − 2 × open issues per 1,000 stars
- Liveness = 100 × exp(−pushed days ago ÷ 120)
Stars, issues, pull requests, and releases are daily observations. Pushed-days and license are repository snapshot-derived inputs and are not independent historical GitHub events.
| Date | Issues opened | Issues closed | PRs opened | PRs merged | Releases | Stars | Open issues | Pushed days ago | Continuity | Closure | Shipping | Liveness | Support burden | License | Observed days | Missing days | Needs healing | Stored score |
|---|
Zitadel
Derived from the displayed continuity, closure, shipping, liveness, and support-burden components.
175 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.30 × Continuity + 0.30 × Closure + 0.20 × Shipping + 0.10 × Liveness + 0.10 × Support burden.
- Continuity = 35% active ratio 90d + 20% active ratio 30d + 15% PR efficiency 90d + 10% PR efficiency 30d + 10% liveness + 10% observed-history coverage
- Closure = 55% PR merge efficiency 90d + 45% issue close efficiency 90d
- Shipping = 100 × (20% × release ratio 30d + 30% × release ratio 90d + 50% × release ratio 180d); ratios are releases ÷ 2, 6, and 12, capped at 1
- Support burden = 100 − 2 × open issues per 1,000 stars
- Liveness = 100 × exp(−pushed days ago ÷ 120)
Stars, issues, pull requests, and releases are daily observations. Pushed-days and license are repository snapshot-derived inputs and are not independent historical GitHub events.
| Date | Issues opened | Issues closed | PRs opened | PRs merged | Releases | Stars | Open issues | Pushed days ago | Continuity | Closure | Shipping | Liveness | Support burden | License | Observed days | Missing days | Needs healing | Stored score |
|---|
node-oidc-provider
Derived from the displayed continuity, closure, shipping, liveness, and support-burden components.
180 observed daily rows. Missing days are not fabricated.
Per-day formula: 0.30 × Continuity + 0.30 × Closure + 0.20 × Shipping + 0.10 × Liveness + 0.10 × Support burden.
- Continuity = 35% active ratio 90d + 20% active ratio 30d + 15% PR efficiency 90d + 10% PR efficiency 30d + 10% liveness + 10% observed-history coverage
- Closure = 55% PR merge efficiency 90d + 45% issue close efficiency 90d
- Shipping = 100 × (20% × release ratio 30d + 30% × release ratio 90d + 50% × release ratio 180d); ratios are releases ÷ 2, 6, and 12, capped at 1
- Support burden = 100 − 2 × open issues per 1,000 stars
- Liveness = 100 × exp(−pushed days ago ÷ 120)
Stars, issues, pull requests, and releases are daily observations. Pushed-days and license are repository snapshot-derived inputs and are not independent historical GitHub events.
| Date | Issues opened | Issues closed | PRs opened | PRs merged | Releases | Stars | Open issues | Pushed days ago | Continuity | Closure | Shipping | Liveness | Support burden | License | Observed days | Missing days | Needs healing | Stored score |
|---|
Hydra is one of several credible self-hosted OAuth2/OIDC options.
| Project | Repo | Hotness (~6mo) | PRs merged (~6mo) | Star growth (~6mo) |
|---|---|---|---|---|
| Ory Hydra | https://github.com/ory/hydra | 5.11 | 0 | 3221 |
| Keycloak | https://github.com/keycloak/keycloak | metrics pending | 0 | 458 |
| Dex | https://github.com/dexidp/dex | metrics pending | 0 | 66 |
| Zitadel | https://github.com/zitadel/zitadel | metrics pending | 0 | 271 |
| Casdoor | https://github.com/casdoor/casdoor | metrics pending | 0 | 155 |
| node-oidc-provider | https://github.com/panva/node-oidc-provider | metrics pending | 0 | 8 |
Keycloak is the most complete standalone option: it includes user management, a built-in login UI, social login, MFA, and an admin console out of the box. The cost is the JVM footprint (typically 1–2 GB RAM at idle) and a steep configuration learning curve. If your team needs working auth with minimal custom code and no existing user store, Keycloak gets there faster. If you need to keep users in your own schema, Hydra's headless model is cleaner.
Dex is a Go-based OIDC federation broker — it aggregates upstream identity providers (LDAP, GitHub, Google, SAML) behind a single OIDC endpoint. Dex is not an authorization server in the full OAuth2 sense; it is an identity broker. Use Dex when your problem is federating enterprise SSO sources, not when you need to issue scoped API access tokens with custom consent flows.
Zitadel is the closest functional alternative to Hydra: Go-based, OIDC-certified, and actively developed. Unlike Hydra, Zitadel includes its own user management and UI, reducing the consent-app burden. If you want Go-native performance without building the consent app yourself, Zitadel is worth a close evaluation.
Casdoor is a Go-based auth server with a built-in web UI and multi-tenant support. It covers OAuth2, OIDC, and SAML and is lighter weight than Keycloak. Less mature than Hydra for production OAuth2.1 compliance requirements, but easier to stand up for simpler use cases.
node-oidc-provider is a JavaScript library for building an OIDC provider inside your Node.js app — not a standalone server. If your stack is Node.js-first and you want to embed OIDC issuer logic directly into an existing Fastify or Express service, this is the most direct path. You build the server wrapper; the library handles the protocol.
Best overall alternative: Zitadel. It matches Hydra's Go-native runtime and active maintenance while adding built-in user management, removing the mandatory consent-app implementation step that blocks most teams from getting Hydra running quickly.
Conclusion
If your team runs its own user database and needs a spec-compliant OAuth2.1 and OIDC authorization server you fully control, Ory Hydra is the right call — the Ory Hydra documentation covers the consent flow, token configuration, and production deployment in enough depth to get from zero to a working integration.
Do not attempt to test OAuth2 flows before your consent app is running — Hydra will redirect users to a consent endpoint that doesn't exist, producing an error_hint: The login verifier returned a flow without response error that is easy to confuse with a Hydra misconfiguration. Start with docker-compose -f quickstart.yml up --build from the Hydra repository, then wire in hydra-login-consent-node as your consent app before writing any integration code.
