Formbricks
Audited from github.com/formbricks/formbricks
Formbricks is an open-source survey and experience-management platform: a Next.js/TypeScript monorepo on Prisma and PostgreSQL, with Redis caching, BullMQ jobs, and Authzed/SpiceDB for fine-grained authorization.
- Language
- TypeScript
- Database
- PostgreSQL
- Hosting
- Docker
- Running for
- 1 year
- Team
- 2-5 people
Why this architecture
A pnpm/Turborepo workspace with a shared dependency catalog lets the web app, background jobs, caching, and AI provider config ship as separate packages while a dedicated Authzed service keeps permission logic out of application code.
Tech stack by layer
6 technologies · audited Sep 17, 2026- Next.jsServes the dashboard, survey editor, and public survey runtime as one app in apps/web.
- Tailwind CSSUtility-first styling for the shared survey UI components.
- Better AuthSession and OAuth authentication for apps/web, replacing the NextAuth/Auth.js setup referenced in the README.
- BoxyHQ SAML JacksonEnterprise SAML/SSO identity provider integration.
- AuthzedZanzibar-style relationship-based authorization service; permission checks run against a committed schema.
- PrismaORM and migration tool for the primary database, in a dedicated @formbricks/database package.
- PostgreSQLPrimary relational datastore, migrated and queried through Prisma; local dev provisions it via Docker.
- RedisUnified caching layer shared across the web app and background jobs, wrapped in @formbricks/cache.
- Dockerapps/web ships a production Dockerfile; docker/ compose files and bootstrap scripts stand up Postgres and Authzed for self-hosting.
- HelmKubernetes deployment ships as a first-class Helm chart, plus a chart for running the SpiceDB/Authzed operator.
- GitHub ActionsRuns API contract/spec tests, Docker build and security scans, Helm chart validation, and staged cloud deploys.
- Vercel AI SDKShared AI provider configuration and model resolution (Bedrock, Azure, Vertex) live in @formbricks/ai.
- BullMQRuns scheduled and background workflow jobs in a dedicated @formbricks/jobs package, over ioredis.
Formbricks architecture diagram
Open SVGDiagram as text
- Dashboard & editor (Next.js) → apps/web (Next.js · Better Auth): HTTPS
- Survey respondents (links · embeds) → apps/web (Next.js · Better Auth): responses
- apps/web (Next.js · Better Auth) → SpiceDB (Authzed permissions): check
- apps/web (Next.js · Better Auth) → PostgreSQL (Prisma): Prisma
- apps/web (Next.js · Better Auth) → Redis (cache · queues): cache · enqueue
- Redis (cache · queues) → Jobs (BullMQ): jobs
- apps/web (Next.js · Better Auth) → SAML SSO (BoxyHQ Jackson): SAML
- apps/web (Next.js · Better Auth) → AI providers (Bedrock · Azure · Vertex): AI SDK
Key architectural decisions
7 decisions- 01
Turborepo pnpm workspace with a single dependency version catalog
pnpm-workspace.yaml scopes the workspace to apps/*, docker, and packages/*, and defines a pnpm catalog (e.g. typescript: 5.9.3) that every workspace references as "catalog:" instead of a literal version; a scripts/check-catalog.mjs check (run by pnpm lint) fails the build if a shared dependency drifts from the catalog or is declared by 2+ packages without a catalog entry.
- 02
Fine-grained authorization is delegated to Authzed/SpiceDB, not in-app RBAC
A committed authzed/schema.zed defines the permission model, apps/web/package.json depends on @authzed/authzed-node, and dedicated scripts (authzed:backfill, authzed:perf, authzed:health, authzed:schema in the root package.json) manage the SpiceDB-based authorization service alongside operational docs in authzed/RUNBOOK.md and authzed/PERFORMANCE.md.
- 03
Auth is migrating from NextAuth/Auth.js to Better Auth
apps/web/package.json depends on @better-auth/core, @better-auth/oauth-provider, and @better-auth/utils, while the README's "Built on Open Source" section still lists Auth.js — the manifest reflects an in-progress migration to Better Auth ahead of the public documentation.
- 04
Redis caching is factored into its own shared package
packages/cache/package.json (@formbricks/cache, described as "Unified Redis cache for Formbricks") depends only on redis and @formbricks/logger, giving apps/web and packages/jobs one shared cache client instead of each implementing its own Redis connection handling.
- 05
Background jobs run in a dedicated BullMQ package, separate from the web app
packages/jobs/package.json (@formbricks/jobs) depends on bullmq and ioredis directly, decoupling scheduled and background workflow execution from the Next.js request/response cycle in apps/web.
- 06
Kubernetes deployment ships as a Helm chart with a SpiceDB operator
The repository tree includes charts/formbricks and charts/spicedb-operator as top-level directories, and a helm-chart-validation.yml GitHub Actions workflow validates them, indicating Helm-based Kubernetes deployment is a first-class, CI-checked deployment target alongside Docker Compose.
- 07
AI provider config is centralized to support multiple LLM backends
packages/ai/package.json (@formbricks/ai, "Shared AI provider configuration and model resolution for Formbricks") depends on @ai-sdk/amazon-bedrock, @ai-sdk/azure, @ai-sdk/google-vertex, and @ai-sdk/openai-compatible together with the Vercel ai package, so AI-backed features are not hard-coded to a single model provider.
How Formbricks is built
How Formbricks is structured
Formbricks is a pnpm/Turborepo monorepo. pnpm-workspace.yaml scopes the workspace to apps/*, docker, and packages/*, and defines a shared dependency catalog (pinned versions like typescript: 5.9.3) that every package references as "catalog:" rather than a literal version, enforced by scripts/check-catalog.mjs. The single application is apps/web (@formbricks/web), a Next.js app; supporting logic is split into focused packages — packages/database (Prisma schema and client), packages/cache (Redis), packages/jobs (BullMQ background jobs), packages/ai (multi-provider LLM config), packages/storage (S3-compatible object storage), packages/email, packages/logger, packages/i18n-utils, packages/types, packages/workflows, and two publishable UI libraries, packages/surveys and packages/survey-ui. A top-level authzed/ directory (schema.zed, RUNBOOK.md, PERFORMANCE.md, INTEGRATION.md) documents a dedicated authorization service that sits alongside, rather than inside, the Next.js app.
Frontend
apps/web is a Next.js app (its dev, build, and start scripts invoke next dev --turbopack, next build, and next start directly). Survey rendering and editing UI is split into two packages consumed by apps/web: packages/survey-ui (@formbricks/survey-ui, described in its own package.json as "React UI components for building surveys and forms... Built with Radix UI and Tailwind CSS") and packages/surveys (@formbricks/surveys, "a helper library to embed surveys into your application"), both built with Vite. Drag-and-drop question ordering uses @dnd-kit/core, and enterprise dashboards embed Cube.js via @cubejs-client/core.
Backend & APIs
Authentication in apps/web depends on @better-auth/core, @better-auth/oauth-provider, and @better-auth/utils — a newer stack than the "Auth.js" the README's tech-stack list still names, suggesting an in-progress migration. Enterprise SSO is handled separately through @boxyhq/saml-jackson. The more distinctive backend decision is authorization: apps/web depends on @authzed/authzed-node, and the root package.json defines authzed:backfill, authzed:perf, authzed:health, and authzed:schema scripts that operate against the schema checked into authzed/schema.zed. This is a Zanzibar-style relationship-based access control system (SpiceDB/Authzed), run and monitored as infrastructure alongside the app rather than expressed purely as in-code role checks — docker/authzed-smoke.sh, docker/authzed-postgres-bootstrap.sh, and docker/authzed-compose-contract.sh bootstrap and test it in CI and local dev.
Data & persistence
packages/database (@formbricks/database) owns the Prisma schema, exposing ./prisma, ./prisma-browser, and ./prisma-adapter subpaths, with a db:migrate:deploy script that runs compiled migration scripts against DATABASE_URL. The presence of PLpgSQL among the repository's top languages, together with the Prisma-based migration tooling, points to PostgreSQL as the primary relational store; docker-compose.dev.yml provisions it for local development. Caching is centralized in packages/cache (@formbricks/cache, "Unified Redis cache for Formbricks"), depending only on the redis client and @formbricks/logger, so both apps/web and packages/jobs share one cache implementation instead of each managing its own Redis connection. Object storage goes through packages/storage (@formbricks/storage), which depends on @aws-sdk/client-s3 and related presigning packages; a docker/rustfs-init.sh script in the tree suggests self-hosted deployments can point that S3 client at a self-hosted, S3-compatible object store rather than AWS S3 directly.
Build, test & deploy
turbo.json defines per-package build graphs — for example @formbricks/database#build depends on @formbricks/database#generate (the Prisma client generation step) before compiling. apps/web/Dockerfile is a multi-stage build pinned to node:24-alpine3.23 (kept in sync with .nvmrc) that enables Corepack, activates pnpm@11.7.0, and reads secrets through a dedicated read-secrets.sh script before running pnpm generate against DATABASE_URL. CI is extensive: .github/workflows includes api-v3-contract-tests.yml and api-v3-spec.yml for API compatibility, docker-build-validation.yml and docker-security-scan.yml, helm-chart-validation.yml, e2e.yml and integration-tests.yml, translation-check.yml, and staged deployment workflows deploy-apollo.yml, deploy-artemis.yml, and deploy-formbricks-cloud.yml.
Self-hosting notes
The README states the Formbricks core is licensed under AGPLv3 and self-hostable via Docker, with a dedicated self-hosting guide linked from the README; docker/README.md and docker/migrate-to-v4.sh cover Docker-based upgrades. For Kubernetes, the repository ships first-class Helm charts under charts/formbricks and charts/spicedb-operator (for running the Authzed/SpiceDB authorization service on-cluster), both validated in CI by helm-chart-validation.yml — self-hosters running on Kubernetes are expected to deploy the authorization service as its own chart rather than embedding it in the main app chart.
What to copy (and what not to)
Extracting cross-cutting concerns — caching (packages/cache), background jobs (packages/jobs), AI provider selection (packages/ai) — into small, single-purpose workspace packages consumed by one Next.js app is a clean way to keep apps/web from becoming a dumping ground, and the pnpm dependency catalog is a practical guard against version drift in a package-heavy monorepo. Running authorization as a separate service (Authzed/SpiceDB) with its own schema, runbook, and Kubernetes operator is a significant investment that pays off at Formbricks' scale of enterprise permission requirements; a smaller app likely does not need a Zanzibar-style ReBAC system and would be better served by simpler in-app role checks. The in-flight Better Auth migration (manifest ahead of README) is also a reminder to verify current dependencies directly rather than trusting a project's own marketing copy.
Sources & repo audit
- Audited
- Sep 17, 2026
- Commit
- 3387e9d
- License
- NOASSERTION
- pnpm-workspace.yaml (dependency catalog)
- apps/web/package.json (Next.js, Better Auth, Authzed, BoxyHQ)
- authzed/schema.zed (SpiceDB permission schema)
- packages/cache/package.json (@formbricks/cache)
- packages/jobs/package.json (@formbricks/jobs, BullMQ)
- packages/ai/package.json (@formbricks/ai, multi-provider AI SDK config)
- README.md (self-hosting, license, "Built on Open Source" stack list)
Independent analysis of repository at github.com/formbricks/formbricks. Spotted an inaccuracy? Use the claim form to request a correction.
Show this stack on your README or website
[](https://stackitfast.com/project/formbricks)Paste it into your README. It shows your current stack and links to this page.
Scaffold it with your agent
Paste this prompt into Claude Code, Cursor, Windsurf or AGY to start a project with Formbricks's architecture.
- 1Copy the promptThe full markdown spec, with every layer and decision.
- 2Open your AI toolClaude Code, Cursor, Windsurf or Copilot, in a new repo.
- 3Paste and scaffoldUse it as the first instruction; review before you ship.
# MISSION: Scaffold "Formbricks" Production Architecture
You are an expert Senior Staff Software Architect and Full-Stack Engineer. Your mission is to scaffold and implement a production-grade, highly reliable, and modular codebase following the proven architecture of **Formbricks**.
---
## 1. PROJECT SPECIFICATIONS & BENCHMARK
- **Reference Architecture**: Formbricks
- **What It Does**: Formbricks is an open-source survey and experience-management platform: a Next.js/TypeScript monorepo on Prisma and PostgreSQL, with Redis caching, BullMQ jobs, and Authzed/SpiceDB for fine-grained authorization.
- **Domain & Category**: Survey & Feedback SaaS
- **Production Scale**: 2-5 people
- **Development Mode**: AI-AGENT
- **Architectural Rationale**: A pnpm/Turborepo workspace with a shared dependency catalog lets the web app, background jobs, caching, and AI provider config ship as separate packages while a dedicated Authzed service keeps permission logic out of application code.
- **Live Website Reference**: https://formbricks.com
- **Source Repository**: https://github.com/formbricks/formbricks
---
## 2. PRODUCTION TECH STACK
- **Full Stack Array**: Next.js, TypeScript, Prisma, PostgreSQL, Redis, SpiceDB
- **Primary Language(s)**: TypeScript, Shell, JavaScript
- **License of the reference repo**: NOASSERTION
- **Frontend**: Next.js — Serves the dashboard, survey editor, and public survey runtime as one app in apps/web.; Tailwind CSS — Utility-first styling for the shared survey UI components.
- **Backend & APIs**: Better Auth — Session and OAuth authentication for apps/web, replacing the NextAuth/Auth.js setup referenced in the README.; BoxyHQ SAML Jackson — Enterprise SAML/SSO identity provider integration.; Authzed — Zanzibar-style relationship-based authorization service; permission checks run against a committed schema.
- **Data & persistence**: Prisma — ORM and migration tool for the primary database, in a dedicated @formbricks/database package.; PostgreSQL — Primary relational datastore, migrated and queried through Prisma; local dev provisions it via Docker.; Redis — Unified caching layer shared across the web app and background jobs, wrapped in @formbricks/cache.
- **Infrastructure & deploy**: Docker — apps/web ships a production Dockerfile; docker/ compose files and bootstrap scripts stand up Postgres and Authzed for self-hosting.; Helm — Kubernetes deployment ships as a first-class Helm chart, plus a chart for running the SpiceDB/Authzed operator.; GitHub Actions — Runs API contract/spec tests, Docker build and security scans, Helm chart validation, and staged cloud deploys.
- **Tooling, testing & ops**: Vercel AI SDK — Shared AI provider configuration and model resolution (Bedrock, Azure, Vertex) live in @formbricks/ai.; BullMQ — Runs scheduled and background workflow jobs in a dedicated @formbricks/jobs package, over ioredis.
---
## 3. KEY ARCHITECTURAL DECISIONS (audited from https://github.com/formbricks/formbricks @ 3387e9d)
1. **Turborepo pnpm workspace with a single dependency version catalog**: pnpm-workspace.yaml scopes the workspace to apps/*, docker, and packages/*, and defines a pnpm catalog (e.g. typescript: 5.9.3) that every workspace references as "catalog:" instead of a literal version; a scripts/check-catalog.mjs check (run by pnpm lint) fails the build if a shared dependency drifts from the catalog or is declared by 2+ packages without a catalog entry.
2. **Fine-grained authorization is delegated to Authzed/SpiceDB, not in-app RBAC**: A committed authzed/schema.zed defines the permission model, apps/web/package.json depends on @authzed/authzed-node, and dedicated scripts (authzed:backfill, authzed:perf, authzed:health, authzed:schema in the root package.json) manage the SpiceDB-based authorization service alongside operational docs in authzed/RUNBOOK.md and authzed/PERFORMANCE.md.
3. **Auth is migrating from NextAuth/Auth.js to Better Auth**: apps/web/package.json depends on @better-auth/core, @better-auth/oauth-provider, and @better-auth/utils, while the README's "Built on Open Source" section still lists Auth.js — the manifest reflects an in-progress migration to Better Auth ahead of the public documentation.
4. **Redis caching is factored into its own shared package**: packages/cache/package.json (@formbricks/cache, described as "Unified Redis cache for Formbricks") depends only on redis and @formbricks/logger, giving apps/web and packages/jobs one shared cache client instead of each implementing its own Redis connection handling.
5. **Background jobs run in a dedicated BullMQ package, separate from the web app**: packages/jobs/package.json (@formbricks/jobs) depends on bullmq and ioredis directly, decoupling scheduled and background workflow execution from the Next.js request/response cycle in apps/web.
6. **Kubernetes deployment ships as a Helm chart with a SpiceDB operator**: The repository tree includes charts/formbricks and charts/spicedb-operator as top-level directories, and a helm-chart-validation.yml GitHub Actions workflow validates them, indicating Helm-based Kubernetes deployment is a first-class, CI-checked deployment target alongside Docker Compose.
7. **AI provider config is centralized to support multiple LLM backends**: packages/ai/package.json (@formbricks/ai, "Shared AI provider configuration and model resolution for Formbricks") depends on @ai-sdk/amazon-bedrock, @ai-sdk/azure, @ai-sdk/google-vertex, and @ai-sdk/openai-compatible together with the Vercel ai package, so AI-backed features are not hard-coded to a single model provider.
---
## 4. NON-NEGOTIABLE ARCHITECTURAL GUARDRAILS
1. **Monorepo & Modular Separation**:
- Structure as a Turborepo monorepo with strict package boundaries:
- `apps/web`: Application UI, routing, layouts, and server endpoints.
- `packages/ui`: Shared design tokens, CSS variables, and Radix UI primitive components.
- `packages/db`: Database schemas, client singleton, declarative migrations, and seed scripts.
- `packages/config`: Shared TypeScript, ESLint, and build configurations.
2. **Strict Type Safety & Zero `any` Policy**:
- Enable `strict: true`, `noImplicitAny: true`, and `strictNullChecks: true`.
- Validate ALL external inputs, API request bodies, and query parameters with **Zod** schemas before execution.
3. **Frontend & Rendering Guidelines**:
- Utilize Next.js 15 App Router: default to React Server Components (RSC) for data fetching. Handle mutations through Server Actions with Zod validation. Keep 'use client' directives restricted strictly to interactive leaf components.
4. **Design System & Aesthetics**:
- Keep every color, radius, shadow and font in a single token file (CSS variables) and consume tokens everywhere; never hardcode hex values in components.
- Prefer crisp 1px borders and one subtle shadow scale over blurry default shadows. Pair one sans-serif for body/headings with one monospace for tags, badges, metrics, and code.
5. **Data Layer & Reliability**:
- Write declarative schema definitions with foreign keys, composite indexes on queried filters, and automated timestamp triggers.
- Use connection pooling and prepared statements for serverless database execution.
---
## 5. STEP-BY-STEP SCAFFOLDING ROADMAP
- **Phase 1: Workspace & Root Config**: Initialize package manager, monorepo configuration (`turbo.json`, `tsconfig.base.json`, `package.json`).
- **Phase 2: Database Schema & Client**: Set up the data layer (Prisma, PostgreSQL, Redis): client, connection pool, models, and migration scripts.
- **Phase 3: Design Tokens & UI Primitives**: Build accessible `Button`, `Input`, `Card`, `Badge`, and layout wrappers inside `packages/ui`.
- **Phase 4: Core Application Routes & Handlers**: Implement primary authentication, user session handling, and application routes.
- **Phase 5: Quality Assurance & Build Verification**: Run `tsc --noEmit`, ESLint, Prettier, and smoke test suites to ensure zero compilation or runtime errors.
---
## 6. EXECUTION INSTRUCTIONS
1. Review all specifications, architectural guardrails, and stack choices above.
2. Present the full monorepo directory tree structure.
3. Systematically generate the complete, production-ready codebase according to the 5-phase roadmap above — starting with the root workspace setup, followed by the database schema, UI design system package, and full-stack application routes until the repository is fully scaffolded and ready to run.Frequently asked about Formbricks
What is Formbricks built with?
Formbricks is a Next.js and TypeScript monorepo using Prisma over PostgreSQL, Redis for caching, BullMQ for background jobs, and Authzed/SpiceDB for fine-grained authorization, managed as a pnpm/Turborepo workspace.
What database does Formbricks use?
PostgreSQL is the primary datastore, accessed through Prisma in a dedicated @formbricks/database package; local development provisions Postgres via Docker Compose (docker-compose.dev.yml).
How does Formbricks handle permissions and access control?
Formbricks delegates fine-grained, relationship-based authorization to Authzed (a hosted SpiceDB service), defined by a committed authzed/schema.zed file and integrated via @authzed/authzed-node in apps/web, rather than implementing role checks purely in application code.
Can I self-host Formbricks?
Yes. The README describes the core application as AGPLv3-licensed and self-hostable via Docker; the repository also ships production-ready Helm charts (charts/formbricks, charts/spicedb-operator) for Kubernetes deployment.
What authentication library does Formbricks use?
apps/web/package.json depends on @better-auth/core, @better-auth/oauth-provider, and @better-auth/utils, indicating a migration to Better Auth, even though the README's stack list still references Auth.js (formerly NextAuth.js).
Does Formbricks support multiple AI providers?
Yes, the packages/ai workspace package centralizes provider configuration for Amazon Bedrock, Azure, Google Vertex AI, and OpenAI-compatible endpoints on top of the Vercel AI SDK, rather than hard-coding a single LLM provider.
One email a month: new deep dives and stack trends
New source-audited architectures, head-to-head comparisons and the monthly stack report. No spam, unsubscribe anytime.
Similar architectures
- UmamiHybridWeb Analytics · SoloShares TypeScript · Next.js · Prisma
- Cal.comClassicScheduling SaaS · 6-20 peopleShares TypeScript · Next.js · PostgreSQL
- TypebotAI-agentConversational Form Builder · SoloShares TypeScript · Next.js · Prisma
- Mem0AI-agentAI Memory & Context Engine · 2-5 peopleShares TypeScript · PostgreSQL · Next.js
- Trigger.devHybridJob Queue / Dev Tool · 6-20 peopleShares TypeScript · Prisma · PostgreSQL
- DocumensoAI-agentE-signature SaaS · 2-5 peopleShares TypeScript · Prisma · PostgreSQL