Skip to main content
Formbricks v6 uses SpiceDB for authorization. Self-hosted installations can upgrade directly from a supported v5 version during a maintenance window; a bridge release is not required for this path. PostgreSQL remains the source of roles and grants. SpiceDB stores the derived authorization graph.
Use only an upgrade pair listed as tested in the target release notes. The formbricks-authzed-prepare executable is available only in images containing this change, not in previously published release candidates. This page is not evidence that a particular v5/v6 pair has passed upgrade and restore testing.

What runs where

Deployment tooling owns maintenance, workload shutdown, infrastructure, and restart. The release image owns database migrations and authorization preparation. Neither the application nor the chart maintains an activation receipt, a migration authority switch, or a second authorization engine for this process. formbricks-authzed-prepare is a preparation command, not an unattended installer. It does not discover or stop writers, suspend controllers, take backups, or restart workloads. Its confirmations are operator acknowledgements, not proof that maintenance is active. Complete and verify those steps first. The command reuses the image’s existing migration runner and formbricks-authzed upgrade prepare and upgrade check implementations. It does not automatically prune unexplained relationships.

Before the maintenance window

  • Rehearse with a restored copy of the installation. Measure migrations, backfill, verification, and restoration time; use those measurements to communicate the maintenance window.
  • Pin the target Formbricks image by digest and the matching chart/Compose files. Preserve the current images, chart, values, secrets, and volume names. Do not combine this change with a PostgreSQL major upgrade, a storage migration, or unrelated Hub/Cube changes.
  • Prepare private SpiceDB connectivity, dedicated datastore credentials, its reviewed version, and completed datastore migrations. Retain existing operator ownership; never install a second operator over an existing cluster-wide operator. See SpiceDB operations.
Identify all writers, including Formbricks replicas, Hub/Hub workers, workflow workers, scheduled jobs, import jobs, integrations, and administrative scripts. Include workloads outside the application namespace or Compose project that write to the same databases. Identify Argo CD/Flux, image updaters, autoscalers, and other controllers that can recreate those workloads. Record their original state for restoration. Do not print Secret contents or expanded Compose configuration into shared CI logs. Prepare and render the exact target manifests before maintenance.

Perform the upgrade

1

Enter and verify maintenance

Serve maintenance at the ingress/reverse proxy and stop accepting new work. Suspend the identified controllers and schedules, stop all writers, and wait for in-flight work and database transactions to finish. Suspending a CronJob does not stop an already-running Job. Scaling a Deployment to zero is insufficient if an autoscaler or GitOps controller can restore it.Verify there are no remaining writer pods, containers, Jobs, external scripts, or active writer transactions. Keep only required infrastructure and the dedicated preparation process running. Keep maintenance active through preparation, restart, and access verification.
2

Take a recoverable backup

Take consistent backups after writers stop, including the application database, existing SpiceDB datastore, and any other datastore changed by the selected release. Retain secrets, configuration, storage state, and exact source images. Confirm the restore procedure has been tested.Online backups taken earlier are useful but are not a substitute for a known recovery point that includes the final writes accepted before maintenance.
3

Prepare using the target image

Run the command below using the exact target image and the same application database and AuthZed configuration that v6 will use. It first validates configuration and authenticated SpiceDB health, then runs application migrations, schema preparation, outbox drain, relationship repair, and a separate full verification. AUTHZED_CONSISTENCY must be fully_consistent.
A non-empty, different SpiceDB schema is not overwritten automatically. Review schema check and the release’s schema changes, then repeat with --expected-current-digest sha256:<reviewed-digest>. Only one preparation/schema-writing process may run at a time.
4

Deploy and test v6 while maintenance remains active

Only after preparation exits 0, deploy the same image digest. Retain fully_consistent and the same datastore bindings. With Helm, set authzed.migrationAcknowledged=true; this is an explicit operator acknowledgement, not a database activation record. The upgrade hook only verifies the prepared graph; it does not apply schemas or backfill while old workloads are running.Verify the actual pod/container image IDs. Through restricted access, test an allowed user, a denied user, a scoped API key, organization/workspace lists, and a grant revocation. Verify outbox delivery, rerun formbricks-authzed upgrade check, and check operational-error metrics. /health alone does not establish authorization readiness.
5

Resume service

Restore controller and worker settings only after their desired manifests point to the tested v6 release. Remove maintenance after the checks pass. Monitor authorization errors, outbox age, revocation delays, and scheduled relationship audits. Keep backups until upgrade acceptance ends.

Docker and one-click

Keep the same Compose project name, database images, and volumes. Prepare a target Compose file that retains customized SMTP, storage, networking, and Traefik settings. Pin formbricks, formbricks-migrate, authzed-ops, and authzed-initialize to the same target image digest. Do not copy a fresh-install Compose file over an existing installation without reviewing those differences. After stopping the old project’s writers and verifying external writers/controllers are stopped, start only the required infrastructure from the reviewed target configuration. Never use down -v. With infrastructure already healthy, run the existing operations service without starting dependencies:
Supply your normal --project-name, --env-file, and -f options when customized. The operator service must receive the application database URL, migration credentials when different, and the six AuthZed client variables. The distributed default uses the bundled PostgreSQL database; customize it when your installation uses a managed database. No database or SpiceDB port needs public exposure. After successful preparation, a one-click installation also sets FORMBRICKS_AUTHZED_V6_MIGRATION_ACKNOWLEDGED=true before its explicit v6 update. Do not invoke an unattended update or move a floating image tag until the release-specific installation tests pass.

Helm and GitOps

Prepare SpiceDB before the application upgrade. Keep the current database/storage settings and existing Secrets. During maintenance, use an explicit, temporary Kubernetes Job with the target Formbricks image, the same database/AuthZed environment bindings, and this command:
This is a template, not a ready-to-apply manifest: set the namespace, digest, resource requests/limits, image-pull credentials, network policy, and environment bindings for your installation. The example Secret must contain the required runtime/migration environment; the chart’s application Secret does not necessarily contain DATABASE_URL or AuthZed values that it normally injects separately. Prefer explicit valueFrom.secretKeyRef bindings to existing Secrets when possible. Never put secrets on a command line or commit their values. Wait for Job completion and inspect its sanitized result before running helm upgrade or resuming an Argo CD/Flux reconciliation. Preparation is not a Helm migration hook or a permanent chart component. Delete the Job and any temporary environment Secret after acceptance; retain only sanitized evidence. There is no activation table to clean up.

Results and recovery

Success prints one JSON result and exits 0:
Blocked preparation exits 2, without a restartRequired field. It never authorizes restarting workloads, including when arguments were rejected before any work ran. The code identifies the failed step: Each subprocess has a 30-minute limit. If the rehearsal exceeds it, budget a longer maintenance window and run the existing migration and operational commands individually under a reviewed Job deadline. Interrupted containers can exit with a signal code rather than JSON; any nonzero exit remains blocked. The command never restarts a workload on success, failure, or interruption. Retry preparation with the same image after correcting the cause, provided the interrupted migration is safe to rerun. Never mark a failed Prisma migration applied without investigating it.

Diagnose migration failures privately

The wrapper deliberately does not offer raw output in shared Job logs: migration errors can contain credentials, SQL, or customer identifiers. In a restricted PostgreSQL operator session, inspect failed Prisma migration records in _prisma_migrations (migration_name, started_at, finished_at, rolled_back_at, and logs). Treat logs as sensitive; do not paste it into CI, tickets, or Slack. For failures before Prisma records the attempt, check connectivity and permissions in that restricted session. If a migration must be retried, first establish whether partial changes need repair, then use the target image’s node /home/nextjs/packages/database/dist/scripts/apply-migrations.js under maintenance. Capture any diagnostic output only in operator-controlled storage; never enable it on normal startup. After database changes, helm rollback or changing the image is not necessarily a safe rollback. Remain in maintenance and either complete the v6 preparation or restore the coordinated backup and matching v5 images/configuration. Resuming writes before restoration risks losing those new writes.

Later v6 upgrades

The same read-only upgrade check gate also applies to v6.x updates. With an unchanged canonical SpiceDB schema and a clean graph/outbox, no additional authorization preparation is needed. One-click stops the stack before application migrations and starts it only after they succeed. Helm keeps its existing application-migration lifecycle; follow the target release’s compatibility and maintenance notes. If a release changes the canonical SpiceDB schema, this flow deliberately blocks the upgrade until explicit maintenance preparation has completed with that target image and a reviewed current digest. Use the procedure above again; the persistent acknowledgement is not permission to skip preparation. An online, backward-compatible schema rollout would need its own reviewed and tested release procedure; neither the Helm hook nor the one-click updater infers that a schema change is safe while writers run.

Cloud is a separate rollout path

Formbricks Cloud can use a temporary, immutable bridge artifact to project relationships while legacy authorization still serves requests, followed by a brief controlled authorization-write pause. That artifact is not a self-hosting prerequisite and does not restore a legacy evaluator to the normal v6 application. Continued read/respondent traffic is a rehearsal requirement, not an unconditional promise of zero downtime.