Which Zitadel deployment model fits your team
Choose the Linux binary or Docker Compose when one node is enough, such as a test environment or an internal pilot where a short outage is acceptable. Choose Kubernetes with the official Helm chart when you need high availability, because Zitadel recommends a Kubernetes cluster for that purpose. PostgreSQL is required in all three models, and self-hosted Zitadel supports PostgreSQL 14 through 18, so the database choice does not change with the deployment path. What does change is availability and the operating skills your team already has, so decide on those first, before comparing feature lists.
Kubernetes is the heavier option, and that weight is the trade-off to price in. Zitadel's production guide suggests a three-node cluster with 4 CPU cores and 16 GB of memory per node as a minimal high availability setup. The kubeadm high availability guide describes at least three control plane nodes with a TCP load balancer in front of kube-apiserver on port 6443. Your team then owns control plane upgrades under the Kubernetes version skew policy, along with etcd backups. Kubernetes ships roughly three minor releases a year, so plan for recurring upgrade work. Ask your platform team whether an existing cluster already meets these requirements, since that determines how much new operating work you take on.
Whichever path you pick, handle initialization and upgrades the same way. Zitadel's production guide suggests running zitadel init and zitadel setup as separate jobs, so scaled workload containers only run the start command and start faster. The binary is stateless and event sourced, so your backups cover the PostgreSQL database, not the binary. For image tags, the stable tag marks the current production release, while latest tracks the most recently created release. Pin stable for production and use latest only in non-production environments, and confirm the upgrade sequence for your target version before you change tags.
Side-by-side: binary, Docker Compose and Kubernetes
This table compares the three documented ways to run Zitadel on the requirements that shape the decision: database, high availability, init and setup jobs, image tags, upgrades, backups and skills. Read each row against your team's operating model and the sizing your environment needs. The main takeaway is that Zitadel's documented high availability path is Kubernetes with the official Helm chart, while the binary and Compose options leave you to design that resilience yourself.
| Requirement | Linux binary | Docker Compose | Kubernetes with Helm chart |
|---|---|---|---|
| PostgreSQL dependency | Requires a PostgreSQL instance. Self-hosted Zitadel supports PostgreSQL 14 to 18. | Requires a PostgreSQL instance. Self-hosted Zitadel supports PostgreSQL 14 to 18. | Same requirement. Confirm in the chart values whether the database is supplied or must be connected. |
| High availability recommendation | Not the documented high availability path. Plan redundancy yourself. | Not the documented high availability path. Plan redundancy yourself. | Documented path: a Kubernetes cluster with the official Helm chart for easy deployment and maintenance. |
| Minimum resources | 1 CPU and 512 MB memory are more than enough for test environments. | 1 CPU and 512 MB memory are more than enough for test environments. | Test: 1 CPU and 512 MB. Minimal high availability: three nodes with 4 CPU cores and 16 GB memory each. |
| Init and setup jobs | Confirm the init and setup steps and their order in the production guide. | Confirm how to run init and setup once, separately from scaled workload containers. | Documented pattern: run init and setup as separate jobs so workload containers only run start. |
| Image tags | Not applicable. Confirm release artifact naming on the GitHub releases page. | Use stable for the current production release or pin a version. Latest tracks the newest build. | Set the image tag in chart values. Stable tracks production, latest tracks the newest pipeline build. |
| Upgrade mechanics | Replace the binary and restart. Confirm required migration steps in each release's notes. | Change the image tag and recreate containers. Confirm migration steps in each release's notes. | Helm upgrade with rolling replacement. Cluster upgrades follow the version skew policy, control plane first. |
| Backup scope | Back up PostgreSQL. The binary is stateless and state can be rebuilt from the eventstore.events2 table. | Back up PostgreSQL. The container holds no state that needs separate backup. | Back up PostgreSQL for Zitadel data. The cluster's etcd also needs its own backup plan. |
| Skills assumed | Linux service administration and PostgreSQL operations. | Docker and Compose file management, plus PostgreSQL operations. | Kubernetes operations, Helm, RBAC, and etcd backup and restore for self-built clusters. |
Which option suits a test, single-site or high availability footprint
Zitadel's self-hosting guide lists Linux, macOS, Docker Compose and Kubernetes as supported platforms, and it still requires a PostgreSQL instance in every case. For a proof of concept, the fastest route is usually whichever option your team can tear down without ceremony. The guide says 1 CPU and 512 MB of memory are more than enough for test environments, so a laptop or a small virtual machine is adequate for exploring the console, organizations and federation settings.
- Fast iteration: Compose or the Linux binary lets you change configuration, restart and reset the database in minutes, which suits trying out organizations, projects and login flows.
- Throwaway data: Test instances often have no backup or restore path, so anything you configure should be treated as disposable unless you exercise the backup procedure now.
- No availability guarantee: A single container or binary cannot show how Zitadel behaves when a node fails, so a sandbox proves features, not resilience.
- Tag discipline: Pin an explicit image tag rather than relying on
latest, since the tag points at the most recently created release and may differ from a production baseline. - Licensing awareness: Zitadel v3 and later are under AGPL-3.0 for core components, so confirm with your legal team whether evaluation use and any later internal exposure fit your obligations.
Before relying on evaluation results, confirm the exact version you will run in production, your PostgreSQL version within the supported range, and the upgrade path from the sandbox configuration to a managed production deployment.
A single production host running Docker Compose or the Linux binary is a reasonable choice for an internal workforce identity service with modest user counts and a team that already operates Docker. The trade-off is that one host and one database become single points of failure, and the vendor's high availability recommendation points to Kubernetes rather than to a single machine. Plan for a maintenance window for upgrades and for database recovery as the main operational risk.
- Simple footprint: One host, one PostgreSQL instance and a reverse proxy in front of Zitadel keep the moving parts few and familiar to a small operations team.
- Separate init and setup: Zitadel's production guide describes running
zitadel initandzitadel setupas separate jobs, so the workload container only runs the start command. On a single host, you must still run those steps in the right order during each upgrade. - Database as the recovery point: The binary is stateless and event sourced, so backups cover the PostgreSQL database rather than the binary. Restoring the database and starting a new container is the core recovery path.
- No automatic failover: If the host or Docker daemon fails, identity services stop until someone intervenes, which affects every application that depends on login.
- Host hardening: Host patching, Docker updates and firewall rules become your responsibility, and they share the same blast radius as Zitadel.
Before going live, confirm your recovery time objective with the business owners, test a full database restore onto a clean host, and verify that your PostgreSQL version falls within the range Zitadel supports.
Zitadel's production setup guide recommends running it highly available with an orchestrator that schedules it across multiple servers, and it suggests a three-node cluster with 4 CPU cores and 16 GB of memory per node as a minimal high availability setup. The official route to that recommendation is Kubernetes with the official Helm chart. This tab is the right choice when you need rolling upgrades, automatic rescheduling and multiple replicas, and when your platform team already runs and monitors a cluster.
- Vendor-backed pattern: Zitadel points to its Helm chart for deployment and maintenance, which gives you a documented starting point rather than a hand-built manifest set.
- Replicas and rescheduling: The orchestrator can keep several Zitadel pods running and replace failed ones, but availability still depends on the database and load balancing layer.
- Cluster is a dependency: Kubernetes itself needs its own control plane, etcd, certificates and upgrade cadence, and Kubernetes releases roughly every 14 weeks, so the identity service inherits that operational load.
- Database high availability is separate: Zitadel's stateless server does not make PostgreSQL highly available, so you need a separate design for database failover and backups.
- Secrets handling: Kubernetes Secrets are stored unencrypted in etcd by default, so confirm encryption at rest and restricted access before storing database credentials there.
Before relying on this design, run a failover test that stops a node and the primary database, measure how long logins take to recover in your environment, and confirm who owns cluster upgrades, etcd backups and the Helm chart version.
What each option runs and where state lives
Each deployment path runs the same Zitadel server and needs a PostgreSQL instance, but the components around it differ. The question for your team is which layers you will operate, patch and back up, and where the authoritative state sits.
Linux binary on a host
The binary runs directly under your init system on a Linux host, with the database connection supplied through configuration. Nothing else is packaged with it, so you own the service unit, TLS termination, restarts and host patching. Because the binary holds no state of its own, replacing the host is a configuration and database exercise rather than a data migration. Confirm how your team will run the init and setup steps before the first start, and who owns that runbook.
Docker Compose services
A Compose file typically groups the Zitadel container, a PostgreSQL container and the reverse proxy in one place, which suits a single host or a small test environment. The containers are disposable, but the PostgreSQL volume is not, so the volume and its backup schedule need the same attention as the database itself. Check how the stack handles restarts and upgrades, since Compose does not provide multi-node scheduling. Pin image tags deliberately rather than relying on the most recent build.
Kubernetes workloads and Helm chart
The official Helm chart creates the Zitadel deployment, its services and configuration, and is the path Zitadel recommends for high availability. Setup and init run as separate jobs, so scaled workload pods only start the server and come up faster. You gain scheduling across nodes, rolling updates and probes, but you also own ingress, secrets handling and resource requests. Ask your platform team which Helm chart version and Zitadel image tag they will pin.
PostgreSQL as the system of record
Every option needs a PostgreSQL instance, and Zitadel stores its events in the eventstore.events2 table, so this database holds the authoritative state. Supported versions are 14 through 18. Because the binary can be rebuilt from the event store, your backup and restore plan is really a database plan, including point-in-time recovery, replication for high availability and tested restores. Decide who operates the database before choosing the deployment path.
Kubernetes control plane and etcd
Kubernetes adds a control plane, and its etcd cluster stores cluster objects, including Secrets, which are unencrypted at rest by default unless you configure encryption. A highly available control plane needs at least three control plane nodes and a load balancer in front of the API server, and etcd should have an odd member count, with five recommended in production. These are burdens the Linux binary and Compose paths do not carry, so count them in your effort estimate. Confirm who runs etcd backups and upgrades.
Load balancer in front of Zitadel
A highly available Zitadel deployment needs an entry point that spreads requests across several server instances and removes failed ones from rotation. In Kubernetes this is usually an ingress or service, while on Linux or Compose it is a proxy you configure yourself. TLS termination, health checks and session behavior sit at this layer, so test failover with real login flows rather than only checking that the port answers. Ask your team which component issues and renews certificates.
Running init and setup jobs before the server starts
Zitadel's production guidance separates one-time initialization from the running server, so each replica only starts the server. The sequence is the same whether you run Docker Compose, a Linux host or Kubernetes, but the place where you enforce it differs, and the database is prepared once before any scaled container starts.
Pin the image tag before any job runs
Choose the image tag for the release you have tested and write it into every job and server definition. Zitadel's image tags distinguish stable, the current production release, from latest, the most recently created release from the pipelines, so stable is the safer default for production. Use the same tag for init, setup and the server so all three come from one release. Done when the tag appears identically in every file or manifest you will apply, and you have recorded it in your change log.
Prepare PostgreSQL before the first job
Provision a PostgreSQL instance in a supported version from 14 through 18, and confirm the Zitadel containers or hosts can reach it on the network. The database holds all state because the binary is stateless and event sourced, so this instance is what your backups must cover. Test the connection from the host or cluster network that will run the jobs, using the credentials you will pass to Zitadel. Done when that test succeeds from the same network the jobs will use.
Run zitadel init as a one-off job
Run zitadel init once, as a standalone job that exits when it finishes. It prepares what the server needs before it can start, and running it apart from the replicas means no two containers attempt it at the same time. Keep it out of the scaled workload definition so the replica count never changes how often it runs. Done when the job exits with a success status and the logs show no connection or permission errors.
Run zitadel setup after init succeeds
Run zitadel setup as a second separate job, and start it only after init has completed successfully. This job completes the setup the server depends on, so the server containers can start against a database that is ready. Keep setup separate from the server definition so a scaled deployment never runs it. Done when the job exits successfully and the eventstore.events2 table is present in the database.
Confirm both jobs finished before replicas start
Check that init and setup have both exited with success before you start any server container. In Docker Compose, the ordering depends on how the service dependency is expressed, and in Helm it depends on how the chart orders hooks and jobs. Do not assume ordering from the order of entries in a file. Done when a test start of one server container reaches its start command without database errors.
Start workload containers with the start command only
Start the server replicas with the start command only, so they do not run init or setup themselves. The production guide presents this separation as the reason scaled containers start faster. Schedule the replicas across multiple servers under an orchestrator, and use the guide's three-node layout with 4 CPU cores and 16 GB of memory per node as the minimal high availability starting point to confirm with your own load. Done when each replica reports ready to your load balancer or orchestrator.
Confirm ordering in your Compose or Helm file
Before you scale, read your own Compose file or Helm values and templates and confirm how the jobs and server are ordered, checking the Zitadel documentation and the chart documentation for the expected behavior. If you use Helm, check whether the chart defines the jobs as hooks and what happens when a job fails. Test a failed init in a non-production environment to see whether the server still starts. Done when you have a written note of the ordering mechanism and a tested failure case.
What a stateless event-sourced server means for backups
The database is the backup target, not the Zitadel binary, the container image or the Helm release. Zitadel's production guidance describes the binary as stateless and event sourced, so the state can be rebuilt from the eventstore.events2 table in PostgreSQL. That holds whichever deployment you choose: a Linux host, a Docker Compose stack or a Kubernetes pod. The practical consequence is that a rebuilt server is only as good as the database copy it reads, so the backup plan should be written around PostgreSQL 14 to 18 and the events it holds, with the server version treated as a replaceable component pinned to a known tag.
Restore testing matters more here than the backup schedule. Restore a copy into a separate environment, start a Zitadel instance against it using the same image tag, and confirm that logins, organizations and applications behave as expected. Run the check on each deployment method you operate and after each upgrade, because the event history is only useful if it replays cleanly. For the database backup method, ask your PostgreSQL team to confirm point-in-time recovery, the retention window and encryption at rest, and whether the chosen tool preserves a consistent snapshot of the event table. Confirm backup tooling with your DBA and with Zitadel before adopting it, since the supplied guidance does not name specific tools as supported.
Configuration and secrets sit outside the event store and must be recoverable separately. Keep environment variables, Compose files, Helm values and the init and setup job definitions in version control, with secrets referenced from a vault or secret store rather than committed in plain text. If those inputs are lost, a restored database can still be unusable. Document which keys, such as the master key or database credentials, you must be able to produce during a recovery drill, and store them under the same access controls as the database backups. Ask your team to name the owner of each item before go-live.
Operating effort: upgrades, backups, monitoring and skills
This table compares who carries each operating task under the Linux binary, Docker Compose and Kubernetes with the official Helm chart. Read it as a split of responsibility: the Kubernetes row adds a cluster layer that someone must patch, back up and monitor on top of Zitadel itself. The main takeaway is that all three options need a PostgreSQL database team, and the Kubernetes option adds the most ongoing platform work.
| Task | Linux binary | Docker Compose | Kubernetes with Helm chart |
|---|---|---|---|
| Zitadel version upgrades | Your team replaces the binary and runs the setup step against the database, after reading the release notes | Your team changes image tags and reruns the setup step, pinning to stable rather than latest for production | Your team updates chart values and image tags, and runs init and setup as separate jobs in the order the chart expects |
| Database backups and restore tests | Your DBA team owns PostgreSQL backups; Zitadel state lives in the database, not the binary | Same ownership; the Compose file does not back up PostgreSQL unless you configure it | Same ownership, plus the cluster team if the database runs inside the cluster |
| Monitoring and alerting | Host and process monitoring, plus PostgreSQL metrics, built by your team | Container and PostgreSQL monitoring, built by your team on a single host | Pod, node and etcd monitoring alongside Zitadel and PostgreSQL, all built by your platform team |
| Certificates and ingress | Your team manages TLS termination and any reverse proxy in front of the binary | Your team manages TLS and a reverse proxy container alongside Zitadel | Your team manages ingress controllers, certificates and the load balancer in front of kube-apiserver and workloads |
| Cluster lifecycle | Not applicable; the host operating system is patched by your existing process | Host operating system and Docker engine patching, owned by your infrastructure team | Kubernetes minor upgrades, one minor version at a time, with kubelets at most three minors behind kube-apiserver |
| Kubernetes version support (context) | Not applicable | Not applicable | The project maintains the three most recent minor releases, with about one year of patch support per minor, so cluster upgrades are recurring work |
| Skills assumed | Linux administration, PostgreSQL operations, TLS and reverse proxy configuration | Linux, Docker, Compose, PostgreSQL operations and TLS | Kubernetes administration, Helm, etcd operations, RBAC, PostgreSQL and ingress design |
| Zitadel high availability | Not offered by the binary alone; multi-host setups need an orchestrator your team builds | Single-host Compose is not a high availability design on its own | Zitadel recommends Kubernetes for high availability, with a three-node minimal setup in its production guide |
Questions teams ask before choosing a Zitadel deployment model
Is Kubernetes required for high availability with Zitadel?
No, Kubernetes is not strictly required, but it is the path Zitadel documents for high availability. Zitadel recommends running the server highly available with an orchestrator that schedules it across multiple servers, and it points to its official Helm chart for deployment and maintenance. Its production guide suggests a three-node cluster with 4 CPU cores and 16 GB of memory per node as a minimal high availability setup. A team that runs Linux binaries or Docker Compose can still build redundancy with its own load balancer and process supervision, but that design is outside the documented recommendation, so confirm the approach with Zitadel before you commit to it. Ask your platform team whether it can operate a Kubernetes cluster at all, because the cluster itself is a larger dependency than Zitadel.
What PostgreSQL work is needed with every Zitadel option?
Every deployment model needs a PostgreSQL instance, and self-hosted Zitadel supports PostgreSQL 14 through 18. The Zitadel database is where its event store lives, so the database is the system of record for identity data. Your team owns provisioning, sizing, patching, high availability for the database, connection and credential management, and backup and restore testing. Those tasks look the same whether Zitadel runs as a binary, a Compose stack or a Kubernetes release, so the choice of deployment model does not remove them. Ask your DBA or database provider to confirm the version, replication design and backup schedule in your environment, and treat the database work as a separate line in any scope.
How much effort does each Zitadel deployment path take to run?
Effort rises as the platform gets more capable. The Linux binary has the fewest moving parts, with the server, its configuration and PostgreSQL to manage. Docker Compose adds a container runtime, image tag discipline and a single-host failure domain, which is simple to start but limited for uptime. Kubernetes with the official Helm chart adds cluster lifecycle, ingress, secrets handling, upgrades and monitoring, and Kubernetes itself has its own support cadence: its three most recent minor releases are maintained, and version skew rules require upgrading the control plane before nodes. Your effort depends on how much of that platform you already run. Ask for the effort split between Zitadel work and platform work in any written scope.
Can a small team operate a self-hosted Zitadel instance alone?
A small team can run Zitadel alone if it already owns PostgreSQL operations and at least one of the chosen platforms well. Zitadel's own test guidance says 1 CPU and 512 MB of memory are more than enough for test environments, but production needs more and high availability needs multiple nodes. The practical question is coverage: who handles an upgrade, a failed database failover, a certificate expiry and an identity outage at 2 a.m. If that is one person, plan for a vendor retainer or a second trained operator. DeployOpen offers ongoing support, upgrades and continuous testing as retainers, and those are priced from a written scope, so ask for a quote that names the coverage hours you need.
How long does a first Zitadel deployment take?
No duration is published here, and the right answer depends on your scope. The time depends on the chosen deployment model, whether you need a highly available topology, how many identity providers you federate, how many organizations and projects you configure, the database setup and your change approval process. A Kubernetes path with an existing cluster is a different job from a single binary on a fresh host. Ask DeployOpen or any implementer for a scoped estimate that lists the deployment model, the integrations, the migration work, the testing and the handover. Most engagements are fixed-scope, so the timeline is agreed in writing before work starts.
What drives the cost of running Zitadel up or down?
Cost has three components: infrastructure, people and the commercial license decision. Infrastructure includes compute for at least three nodes if you pursue high availability, the PostgreSQL instance and its backups, storage and load balancing. People cost covers the internal time to operate the platform and the external services you buy for implementation, integration and support. Licensing matters too, because Zitadel v3 moved its core to AGPL-3.0, so teams that cannot accept that license should review Zitadel's commercial option before scoping. Costs rise with the number of environments, the size of the high availability cluster and the amount of federation and migration work. Costs fall when you standardize on a platform you already run and keep the topology as simple as your uptime target allows. Ask any quote to itemize infrastructure, implementation, testing, handover and retainer hours separately.
Which Zitadel image tag should we pin in production?
Pin a versioned release rather than following the most recent build. Zitadel's image tags separate stable, which is the current production release, from latest, which is the most recently created release from its pipelines. Using latest in production means an upgrade can arrive without a planned change window. Record the exact version you deploy, read the release notes for each upgrade, and test the upgrade against a copy of your database before rolling it to production. At the time of this page, the current Zitadel release is v4.19.5, released on October 15, 2026, so confirm which tag your team has validated before you copy it into a manifest.
What drives the cost of each deployment path
Zitadel is licensed under AGPL-3.0 for self-hosting, so the software itself carries no license fee. The money goes to four places: the compute and storage for the Zitadel nodes, a PostgreSQL instance that you or a provider operates (Zitadel requires PostgreSQL 14 to 18 in every path), the cluster the Kubernetes path depends on, and people. Staff time is the largest and least visible line. Someone must design the deployment, harden it, run restore tests and keep it upgraded. A single Linux host or a Compose stack costs less to run than a Kubernetes cluster that your team must also operate, but the database and backup work are the same in each case. Price the path by who will carry the pager, not by the server count.
Split the work into one-time and recurring items before you compare quotes. One-time work covers architecture and sizing, installation, TLS and secrets handling, identity provider and application integration, hardening, and a restore test that proves the PostgreSQL backups bring Zitadel back. Recurring work covers Zitadel upgrades (checking the stable tag against the Zitadel GitHub releases page), patching the host or cluster, PostgreSQL maintenance, monitoring and periodic restore drills. For the Kubernetes path, add cluster upgrades, which follow the Kubernetes version skew policy and recur about three times per year according to the Kubernetes release cycle. Ask the vendor or partner to split each quote into these two columns so the recurring figure is visible for every year you run the platform.
Zitadel's production guide describes a minimal high availability setup of three nodes with 4 CPU cores and 16 GB of memory each, plus a PostgreSQL database. Treat that as a documented starting point, not a sizing for your load. Ask any quote to state the node count, instance sizes, database topology, backup retention, who gets paged and what happens during an upgrade. Ask whether the scope covers the init and setup jobs, which should run separately from the scaled server containers, and whether the Helm chart or Compose file is maintained as part of the handover. For a cloud comparison, the Zitadel pricing page publishes the vendor's own plan terms, which you should read alongside a self-hosted estimate built from your own quote.
How DeployOpen works on this
DeployOpen is a Chainscore Labs company that plans, implements, hardens, backs up, documents and supports self-hosted open-source platforms inside the client's own infrastructure. For Zitadel, we start by choosing the deployment method that fits your operating model, then build and document it in your environment.
How we scope
- We confirm which method your team will run: Linux binary, Docker Compose or Kubernetes with the official Helm chart.
- We record the PostgreSQL version, hosting location, backup targets and high availability goals in the written scope.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before any work starts.
How we build
- We deploy Zitadel with init and setup run as separate jobs, and pin the image tag your team chooses.
- We configure PostgreSQL connectivity and backups, then test restores against the event store data.
- We test identity flows such as OIDC, SAML and SCIM against your applications in a staging environment first.
How we hand over
- We document the deployment, upgrade steps, configuration keys and recovery procedures for your own operators.
- We walk your platform and security teams through the runbooks and the reasons behind each design choice.
- We provide evidence for your internal reviews, while independent auditors remain responsible for any formal assessment.
How we support
- Ongoing support, upgrades and continuous testing are available as retainers after handover.
- We can plan upgrades around Zitadel release notes and your own change windows, with testing before each rollout.
- Ask any provider, including DeployOpen, to confirm in writing which environment, versions and responsibilities a quote covers.

