Skip to main content
Deploy Formbricks on Kubernetes using the current OCI Helm chart published from the charts/formbricks directory in the Formbricks repository.
Formbricks v5 self-hosting expects Hub to be part of the runtime. The chart handles that by default. Use the migration guide before upgrading an existing 4.x deployment.

Prerequisites

Ensure you have the following before proceeding:
  • a running Kubernetes cluster
  • Helm 3 installed locally
  • a public hostname for formbricks.webappUrl
  • a plan for PostgreSQL and Redis/Valkey, either in-cluster or managed externally
  • an edge rate-limiting plan for the v5-covered routes: the chart’s Envoy bundle or an equivalent external edge solution

1. Install The Chart

1

Create A Minimal values.yaml

Add any additional overrides you need for ingress, external services, secrets, or Enterprise license features.
2

Install Formbricks

By default, the chart deploys:
  • the Formbricks application
  • Formbricks Hub
  • Cube
  • PostgreSQL
  • Redis
  • generated Kubernetes Secrets
The default values are a starting point, not a production edge or high-availability configuration. Both ingress.enabled and envoy.enabled default to false, so the chart does not expose the application or add the v5 edge rate limits unless you configure them. The defaults also combine autoscaling.minReplicas: 1 with pdb.minAvailable: 1; that PodDisruptionBudget can block a node drain because Kubernetes cannot voluntarily evict the only app pod.

2. Configure Secrets And External Services

Using Generated Secrets

The default chart path keeps secret.enabled: true, which lets the chart generate the required application secrets for you.

Adding An Enterprise License

There is no separate enterprise.enabled switch. Enterprise features are unlocked by a valid ENTERPRISE_LICENSE_KEY. For a quick-start deployment that uses the chart-generated app Secret, set:
For production, keep the license out of a values file and provide ENTERPRISE_LICENSE_KEY through your existing Secret or ExternalSecret instead. The enterprise.licenseKey chart value only writes to the generated app Secret when secret.enabled: true.

Using Managed PostgreSQL And Redis

For production workloads, many teams prefer managed services:

Using External Secrets

If your cluster already uses an external secret manager, enable externalSecret and point it at your existing SecretStore. Ensure the resulting app secret exposes the values your deployment needs, including DATABASE_URL, REDIS_URL, and HUB_API_KEY.

SpiceDB authorization

Formbricks v6 uses SpiceDB, maintained by AuthZed, as its authorization engine. Fresh chart installations enable a private, two-replica SpiceDB cluster and fully_consistent decisions by default. If the cluster already has a compatible SpiceDB operator, keep the authorization runtime enabled but disable this release’s operator installation:
The default authzed.operator.install: true installs the pinned operator, creates the cluster, and bootstraps a dedicated spicedb database and login. Install only one operator in a Kubernetes cluster. For managed PostgreSQL, create a separate SpiceDB database and login first. Store its connection URI and a strong API token in a Kubernetes Secret using the keys datastore_uri and preshared_key, then configure:
Use authzed.mode: external, authzed.operator.install: false, authzed.endpoint: <host>:<port>, and authzed.insecure: false when connecting to an externally managed AuthZed endpoint. The external endpoint must serve TLS because the preshared token is sent on every authenticated request. The application endpoint remains internal and uses plaintext gRPC by default when the chart owns SpiceDB. For an already-running v6 installation, Helm prints release-specific diagnostic commands that execute the release-matched operator CLI inside a Formbricks pod:
A fresh install runs an idempotent initialization Job, but application startup and probes remain independent from it. Upgrades never run relationship preparation automatically. For an existing v5 installation, follow the v6 upgrade procedure below before running helm upgrade or resuming GitOps. The chart refuses an unacknowledged upgrade, disabled AuthZed, or weaker consistency. Follow AuthZed Operations for ongoing operations and do not expose SpiceDB through an Ingress.

3. v5-Specific Deployment Notes

Hub Is Mandatory

Formbricks v5 does not support hub.enabled=false. Keep the default hub.enabled=true behavior in place. Use hub.image.tag, hub.resources, and hub.existingSecret only when you need to pin or customize the Hub deployment details.

Envoy Bundle Modes

The chart supports these edge patterns for the v5-covered routes:
  • Bundled Envoy controller and CRDs: set envoy.enabled=true, envoy.controller.enabled=true, and envoy.crds.enabled=true
  • Bundled Envoy controller with platform-managed CRDs: keep the controller enabled and set envoy.crds.enabled=false
  • Existing cluster Envoy controller: set envoy.enabled=true, envoy.controller.enabled=false, envoy.formbricks.gatewayClass.create=false, and envoy.formbricks.gatewayClass.name to the existing class
  • Equivalent external edge protection: keep using your platform’s own ingress or gateway layer if it already provides equivalent rate-limiting coverage
If you use the chart-managed Envoy rate-limiting path, enable a dedicated backend with:
This installs Envoy Gateway 1.8.4 with Gateway API 1.5.1 and keeps Envoy rate-limiting state separate from the application’s own Redis traffic. If your platform already manages compatible Gateway API CRDs, install only the matching Envoy Gateway CRDs:
Pulling the OCI chart first keeps Helm 4’s pull messages out of the manifest pipe. Remove the temporary directory after the apply succeeds. Then keep the bundled controller but prevent the Formbricks release from managing either CRD set:
For a Flux HelmRelease, also make the ownership boundary explicit:
The example installs the bundled controller. If your cluster already provides a compatible Envoy Gateway controller, set envoy.controller.enabled: false, disable GatewayClass creation, and provide the existing GatewayClass name. The controller dependency, including its CRDs, is disabled in this mode. In either mode, configure envoy.formbricks.ingress or your platform ingress/load balancer so public traffic reaches the Envoy-managed routes. If you use an equivalent external edge solution instead, verify that it covers every route in the rate-limiting guide before exposing Formbricks.
Istio and other Gateway API implementations can remain in front of Formbricks, but they do not reconcile Envoy-specific resources such as SecurityPolicy, HTTPRouteFilter, or EnvoyProxy. Enabling the Feedback Records gateway route therefore still requires an Envoy Gateway controller.

Production Replicas And Disruption Budgets

For a production deployment that should remain available during a voluntary disruption, run at least two app replicas:
If you intentionally run a single app replica, either disable the PDB or use maxUnavailable: 1 instead of minAvailable and accept downtime during the eviction. Never set both fields; set the unused field to null in your values file. Two autoscaling defaults are easy to miss:
  • maxReplicas: 10 can exceed what the node pool can hold. Each app pod requests 1 vCPU, so the ceiling needs about 10 allocatable vCPU for the app alone, on top of the platform reserve and the Hub, Cube and SpiceDB pods. A smaller pool leaves the extra replicas Pending — an HPA does not lower its own ceiling.
  • The HPA scales on CPU and memory utilization only. Queue depth is not one of its metrics, so a job backlog can grow while both targets sit under their thresholds and no replica is added. Backlog-driven scaling needs a queue-depth metric published to the metrics API and added to the HPA yourself.

Cube

Cube is part of the baseline Formbricks v5 stack and is bundled with the chart by default (cube.enabled: true). To run an external Cube cluster instead:
  • set cube.enabled: false to skip the bundled Cube deployment
  • point the app at your external endpoint via deployment.env.CUBEJS_API_URL
  • supply CUBEJS_API_SECRET via deployment.env or deployment.envFrom if you disable generated secrets

Optional Bundled Qwen/vLLM For AI

The Helm chart can optionally deploy a Formbricks-provided Qwen runtime through vLLM. This is disabled by default and requires GPU-capable Kubernetes nodes. To deploy Qwen/vLLM and automatically point the Formbricks app at the in-cluster OpenAI-compatible endpoint:
With llm.enabled: true, the chart renders the vLLM router and Qwen serving engine, then injects the required AI_PROVIDER=openai-compatible app environment variables unless you override them in deployment.env. If you want to deploy the bundled Qwen runtime without changing the Formbricks app AI configuration:
Keep llm.enabled: false when you use Google Vertex, Azure, AWS Bedrock, or an externally managed OpenAI-compatible endpoint. Configure those providers through deployment.env.

Optional AI Taxonomy Beta

The Helm chart can optionally deploy the standalone taxonomy service. This is disabled by default and does not force the bundled Qwen/vLLM runtime. To deploy taxonomy and reuse the bundled Qwen/vLLM runtime:
With this setup, taxonomy uses the in-cluster vLLM router for cluster labeling and 5-level taxonomy generation. The chart also injects TAXONOMY_SERVICE_URL, TAXONOMY_SERVICE_TOKEN, and HUB_INTERNAL_API_TOKEN into Hub API. To use your own OpenAI-compatible LLM endpoint instead, keep llm.enabled: false and set the taxonomy LLM values:
The taxonomy-llm-secret secret must contain TAXONOMY_LLM_API_KEY. If your endpoint does not enforce authentication, store a non-empty dummy value. To use Gemini on Vertex AI instead, keep llm.enabled: false, create a secret containing TAXONOMY_GOOGLE_CLOUD_CREDENTIALS_JSON, and configure the Vertex provider:
The service account in TAXONOMY_GOOGLE_CLOUD_CREDENTIALS_JSON must be allowed to call Vertex AI for the selected project and location. After startup, run the authenticated preflight check from inside the taxonomy pod:
The taxonomy service is internal-only by default. Kubernetes probes use public /health; /v1/preflight is for operator validation and requires the internal taxonomy bearer token.

4. Upgrade The Deployment

Upgrading from v5 to v6

Use the v6 maintenance upgrade guide for the complete procedure, temporary Job template, and recovery instructions. Use only an upgrade pair listed as tested in the target release notes. Pin the target Formbricks image by digest and the matching chart version; preserve existing database, storage, and Secret bindings.
1

Enter maintenance and take backups

Prepare private SpiceDB connectivity and complete its datastore migrations before the application upgrade. Suspend GitOps reconciliation, autoscalers, image updaters, and schedules that could restart writers. Stop all writers, including application replicas, Hub/workflow workers, running Jobs, and external integrations, then wait for in-flight work and database transactions to finish. Take recoverable backups after writers stop and keep maintenance active through preparation and access verification.
2

Prepare with the target v6 image

Run an explicit, temporary Kubernetes Job using the exact target image and the database/AuthZed environment bindings that v6 will use, including AUTHZED_CONSISTENCY=fully_consistent. Run this command in that Job, not in an existing v5 application pod:
The command validates configuration and SpiceDB health, runs application database migrations, prepares the schema, drains the outbox, repairs relationships, and performs a separate final upgrade check. The flags acknowledge prerequisites you have already verified; they do not stop workloads or take backups. Review any non-empty schema mismatch using the guide’s guarded replacement procedure.
3

Deploy only after preparation succeeds

Require the preparation Job to exit 0, then set authzed.migrationAcknowledged: true and deploy the same image digest with the reviewed chart version. The Helm pre-upgrade hook verifies the prepared graph; it does not run database migrations, apply the schema, or backfill relationships. Verify authorization and outbox delivery before restoring controllers, workers, and public traffic as described in the guide.
If preparation fails, remain in maintenance. After database changes, helm rollback or switching back to a v5 image may be unsafe; recovery may require restoring the coordinated backups. /health alone does not establish authorization readiness.

Later chart upgrades

For later v6 upgrades, follow the target release’s compatibility and maintenance notes. A changed canonical SpiceDB schema requires explicit preparation again; a previous migration acknowledgement does not bypass verification. For a compatible routine upgrade:
For a Formbricks 4.x to 5.0 migration, confirm the following before running the upgrade:
  • Hub remains enabled
  • HUB_API_KEY is present
  • your edge rate-limiting plan is in place
  • any required AI_* variables are added
  • CUBEJS_API_SECRET is configured (the generated app secret supplies it by default; provide an external endpoint if you set cube.enabled: false)

5. Key Values

For the complete values surface, refer to the chart README in the repository: charts/formbricks/README.md.

6. Uninstalling The Deployment

To remove the deployment:
If you also want to remove in-cluster persistent volumes: