references/sources.md
Sources and further reading
Cross-checked against the official documentation and the upstream repository. Where guidance conflicted, cmd/defaults.yaml in the source tree won, since it is the only description of the configuration that cannot drift from the binary.
Everything in the deployment, token-settings, audience and mobile sections was verified against a live v4.16.0 instance behind Dokploy and Traefik, including a complete Authorization Code + PKCE exchange, JWKS verification and introspection. Measured figures are from that instance, not estimates.
Configuration
cmd/defaults.yaml, upstream - the authoritative reference for every setting, with inline comments- Runtime settings and environment variables
- TLS modes
- External ZITADEL access and custom domains
Reverse proxy
- Reverse proxy configuration
- ZITADEL with Traefik
- ZITADEL with NGINX
- Traefik: exposing services, including h2c
- Dokploy: Docker Compose domains
Concepts and structure
OIDC and integration
- ZITADEL scopes reference - including the
urn:zitadel:*extended scopes - OAuth 2.0 recommended flows
- RFC 8252, OAuth 2.0 for Native Apps - system browser requirement, loopback and custom-scheme redirects
- RFC 7662, Token Introspection
- RFC 7636, PKCE
- OAuth 2.0 for Browser-Based Applications - the BFF guidance
- zitadel/example-auth-nextjs - official Auth.js example, useful as a reference and explicitly not production code
Service accounts, federation and actions
Read for untested.md. Documentation only, not verified against a running instance, unlike everything else cited here.
- Authenticate service accounts - note the path is
service-accounts, notservice-users - Private Key JWT for service accounts
- Client credentials for service accounts
- Access ZITADEL APIs - the
urn:zitadel:iam:org:project:id:zitadel:audscope and manager roles - Roles and role assignments
- Granted projects - cross-organization delegation
- Identity providers - instance-level versus organization-level
- Authenticate users with SAML and SAML endpoints
- MockSAML as an IdP - the cheapest way to exercise SAML without an enterprise IdP
- Actions v2 concepts and using actions
- Migrating from Actions v1 to v2 - v1 ran JavaScript in-process, v2 calls your webhook
- Why Actions v2 shifted to cloud-native orchestration
Operations
- Update and scale
- Release cycle
- Technical advisories - subscribe to this, do not skim it at upgrade time
- Safely upgrading ZITADEL
- Database configuration
- Scaling cloud-native identity: optimizing performance with caching
- Pricing
Provisioning
- Official Terraform provider - Apache 2.0, maintained upstream
- CLI overview - the operator CLI only; there is no official management CLI
- roylee17/zitadel-cli - community, the most complete of the unofficial CLIs
Upstream issues referenced
- #12065 - HTTP used for the discovery document despite
ExternalSecure=true, behind Traefik. Open. - #4475 - the older Traefik variant of the same report.
- #9912 -
environment.jsonlisting the internal IP rather than the external domain. Fixed. - #9109 - PostgreSQL read replica support. Open, and the reason Postgres scales vertically only.
Which claims here are opinion
Worth arguing with, because they are judgement rather than documentation.
- One instance per client. Defensible for an agency holding other people's user
data. The wrong call if you are building a platform product where clients are tenants you serve, in which case one instance with organizations as customers is correct. That is a business model decision wearing an architecture costume.
- Validate audience against the project ID. Pragmatic and future-proof, but it
is a deliberate choice to make every application in a project accept every other's tokens. If your applications genuinely need separate trust domains, the right fix is separate projects, not a narrower audience check.
- BFF over tokens in the browser. Strongly held and occasionally overkill.
Public-client PKCE remains legitimate, and for a statically hosted frontend on a different registrable domain it is more honest than fighting third-party cookie restrictions.
- Access token lifetime of 5 to 15 minutes. A rule of thumb. The right number
depends on how bad a stale token is for your domain and how well your clients handle refresh. The defensible part is that 12 hours, the default, is wrong for almost everyone.
- Never TTL-cache introspection. Follows from treating a short-lived JWT as the
cache. Someone running an extremely high-volume sensitive endpoint against a constrained Postgres might reasonably disagree; they should probably fix the endpoint instead.
- ZITADEL over an in-app library like Better Auth. This follows from needing
both TypeScript and Python. For a purely TypeScript shop, Better Auth's organization plugin covers most of what the reusable module would have been, at zero operational cost, and the recommendation flips.
- Organizations in the application database for anything that is not B2B SaaS.
Simpler and transactional, but it gives up per-tenant SSO and branding, and retrofitting means mirroring into ZITADEL anyway.
- JIT provisioning over webhook sync. Robust, but a user does not exist in your
database until they first authenticate, which complicates admin flows that want to reference someone before their first login.
- "You will never need to scale this." True for the traffic profile of typical
agency client work. Wrong the moment one client's consumer app succeeds, and the read-replica limitation means the ceiling arrives sooner than a stateless binary suggests.
- Terraform rather than a community CLI. Conservative. The community CLIs are
fine for exploration; the objection is specifically about unaffiliated tooling in a client-facing pipeline.