Building a Multi-Tenant SaaS on Bubble.io
The complete technical blueprint: workspace isolation, role-based access control, Stripe subscription billing, team invitations, usage limits, onboarding flows, and production-grade security — all built correctly in Bubble from day one.
What is Multi-Tenancy & Why It’s the Hardest Thing to Get Right
Multi-tenancy is the architecture that powers every B2B SaaS you’ve ever used — Slack, Notion, Linear, HubSpot, Jira. It means a single application serves multiple independent customers (“tenants”), each with their own data, their own team members, their own settings, and their own billing — all in complete isolation from every other tenant. Tenant A can never see, access, or interfere with Tenant B’s data.
This sounds simple. It is not. Multi-tenancy is the single most consequential architectural decision in any SaaS product, and it’s the pattern most commonly botched by first-time Bubble SaaS builders. Getting it wrong early means refactoring every data type, every workflow, and every privacy rule later — typically after you already have paying customers whose data has leaked across tenant boundaries. This guide exists so you never have to do that.
The Six Pillars of a Multi-Tenant SaaS on Bubble
Workspace Layer
A Workspace data type that is the container for all tenant data. Every other data type has a relationship field to Workspace. No data exists without a workspace owner.
Membership & Roles
A Membership junction type connecting Users to Workspaces with a role (Owner, Admin, Member, Viewer). One user can belong to multiple workspaces with different roles in each.
Privacy Rules (Isolation)
Bubble privacy rules that ensure every data type is only visible to members of the workspace that owns it. This is the enforcement layer — without it, tenancy is theatrical, not real.
Subscription Billing
Billing tied to the workspace, not the individual user. The workspace owner pays. Subscription status, plan limits, and seat counts all live on the Workspace record via Stripe.
Invitation System
A secure mechanism for workspace owners and admins to invite new users by email, with token-based acceptance flows that handle both new and existing Bubble users.
Usage Limit Enforcement
Every plan has limits: seats, records, API calls, storage. The app must check limits before creation actions and display current usage to workspace admins in real time.
Multi-Tenancy Architecture: The Full Stack
Acme Corp
Globex Inc
Initech LLC
N tenants…
Shared codebase · Shared infrastructure · Isolated data per workspace
The Core Multi-Tenant Data Model
Before you touch the Design tab, nail this data model. Every other decision in your SaaS build depends on it. These six data types form the non-negotiable foundation of every multi-tenant Bubble SaaS. Build them exactly as described — their relationships to each other cannot be easily redesigned once you have production data.
The Golden Rule: Every Data Type Gets a Workspace Field
Every data type you create for your product — Projects, Tasks, Documents, Invoices, Contacts, whatever your app manages — must have a workspace field of type Workspace. This foreign key is what makes your privacy rules enforceable. Without it, there is no way to scope any search to a single tenant’s data.
Store current_workspace on the User Record
Add a current_workspace field of type Workspace to the User data type. This is the user’s currently active workspace. Every search in your app uses Current User’s current_workspace as its workspace constraint. When a user switches workspace, update this field and reload the page. Never derive workspace context from URL parameters alone — it creates subtle inconsistencies and can be manipulated.
Privacy Rules: The Actual Enforcement Layer
The data model defines the structure of your tenancy. Privacy rules are what actually enforce it. Without properly configured privacy rules, your workspace fields are decorative — any user can still search any data type and retrieve records from every tenant. Privacy rules are Bubble’s server-side access control layer, and they must be configured correctly on every single data type in your app.
The fundamental principle: a user should only be able to see a record if they are an active member of the workspace that owns that record. Every privacy rule you write is a variation of this principle.
The Core Privacy Rule Pattern
Privacy Rule Reference: All Six Core Data Types
| Data Type | Privacy Condition | View | Edit | Delete | Search |
|---|---|---|---|---|---|
| Workspace | Membership exists: user = Current User, workspace = This Workspace, status = Active | ✓ | Owner & Admin only (2nd rule) | Owner only (2nd rule) | ✓ |
| Membership | This Membership’s workspace has any active Membership with user = Current User | ✓ | Self or Admin/Owner | Admin/Owner only | ✓ |
| Invitation | This Invitation’s workspace has active Membership for Current User — OR — token matches URL param (unauthed accept) | ✓ | ✗ | Admin/Owner only | ✓ |
| User | Current User (self) — OR — shares any active workspace Membership with Current User | Limited fields | Self only | ✗ | ✓ |
| Audit Log | Membership exists: user = Current User, workspace = This Log’s workspace, role = Owner or Admin | ✓ | ✗ | ✗ | ✓ |
| Plan | Everyone (public data — plan features should be publicly readable) | ✓ | ✗ | ✗ | ✓ |
| App data types (Project, Task, Doc…) |
Active Membership exists: user = Current User, workspace = This Record’s workspace | ✓ | Member+ (role check) | Admin/Owner (role check) | ✓ |
Adding Role-Based Edit & Delete Controls
Bubble privacy rules support multiple rules per data type. Add a second rule on each type to control edit and delete permissions based on role. The first rule handles view access for all workspace members; the second rule adds edit/delete gating based on membership role.
Never Use “Everyone” on App Data Types
Bubble has a special privacy rule option called “Everyone” that makes records accessible without any condition. Never use this on any data type that belongs to a workspace. It is only appropriate for truly public data like Plan details or public marketing content. A common beginner mistake is leaving the default “Everyone” rule on newly created data types while building, then forgetting to restrict it before launch. Do a full privacy rule audit before going live.
Role-Based Access Control (RBAC)
Most B2B SaaS products have 3–4 roles within a workspace. The most common pattern is Owner, Admin, Member, and Viewer. Roles are stored on the Membership record, not on the User record — because the same user can be an Admin in one workspace and a Member in another. Never store roles on the User.
The Four-Role System (Option Set Definition)
Full Permission Matrix: What Each Role Can Do
| Action | Owner | Admin | Member | Viewer |
|---|---|---|---|---|
| ▶ WORKSPACE MANAGEMENT | ||||
| Edit workspace name / logo | ✓ | ✓ | ✗ | ✗ |
| View billing & subscription | ✓ | ✓ | ✗ | ✗ |
| Upgrade / downgrade plan | ✓ | ✗ | ✗ | ✗ |
| Delete workspace | ✓ | ✗ | ✗ | ✗ |
| Transfer ownership | ✓ | ✗ | ✗ | ✗ |
| ▶ TEAM MANAGEMENT | ||||
| Invite new members | ✓ | ✓ | ✗ | ✗ |
| Remove members | ✓ | ✓ | ✗ | ✗ |
| Change member roles | ✓ | Admin & below | ✗ | ✗ |
| View team list | ✓ | ✓ | ✓ | ✓ |
| ▶ DATA ACTIONS | ||||
| View all workspace records | ✓ | ✓ | ✓ | ✓ |
| Create new records | ✓ | ✓ | ✓ | ✗ |
| Edit own records | ✓ | ✓ | ✓ | ✗ |
| Edit others’ records | ✓ | ✓ | ✗ | ✗ |
| Delete records | ✓ | ✓ | Own only | ✗ |
| View audit log | ✓ | ✓ | ✗ | ✗ |
| ▶ LEAVING & ACCOUNT | ||||
| Leave workspace | Transfer first | ✓ | ✓ | ✓ |
| Switch active workspace | ✓ | ✓ | ✓ | ✓ |
Enforcing Roles in Workflows (Not Just in the UI)
Hiding a button based on role is UI-level protection only. An advanced user can trigger workflows directly via API calls if backend protection is missing. Every sensitive action must have a role check inside the workflow itself, not just in the UI conditional that shows the trigger button.
The Team Invitation System
Inviting team members to a workspace is one of the most technically nuanced flows in any multi-tenant SaaS. It must handle two distinct cases: inviting someone who already has an account in your app, and inviting someone who doesn’t yet exist as a user. The invitation must be secure (token-based), expire after a set period, and correctly create a Membership record regardless of which path the invited person takes.
The Complete Invitation Flow
Before sending: check seat limit. If Workspace’s seats_used ≥ Workspace’s plan’s seat_limit, block and show upgrade prompt. Otherwise proceed.
They land on /accept-invite with the token as a URL parameter. The page loads the Invitation by token. First validate: token exists, status = Pending, expires_at > now. If any check fails, show an appropriate error message.
The page must detect whether the invited email already belongs to a Bubble user. Show either a login form or a sign-up form accordingly. The token must be preserved through both paths.
Stripe Subscription Billing for Multi-Tenant SaaS
In a multi-tenant SaaS, billing is workspace-level, not user-level. One workspace has one Stripe Customer, one active Subscription, and one billing contact (the owner). Every billing action — checkout, upgrade, downgrade, cancellation — is initiated by the workspace owner on behalf of the workspace. Never create a Stripe Customer per user.
SaaS Pricing Strategy Built in Bubble
The Stripe Integration Architecture
Stripe Webhook Handlers: The Six You Must Build
Stripe webhooks are how your Bubble app stays in sync with billing reality. Do not rely solely on the post-checkout redirect to update subscription status — payment failures, cancellations, and renewals all happen outside the user’s active session. You need webhook handlers for all of these events.
Validate Stripe Webhook Signatures
Any server can send a POST request to your Bubble webhook endpoint claiming to be Stripe. Stripe signs every webhook with a secret you set in the Stripe dashboard. Use the Stripe Webhook Validator plugin (or the API Connector) to verify the Stripe-Signature header on every incoming webhook before processing it. An unvalidated webhook endpoint is a critical security vulnerability that allows anyone to fake billing events.
Usage Limits & Plan Enforcement
Plan limits are what turns your SaaS into a business model. Every plan has limits on seats, records, storage, or feature access. Enforcing these limits correctly is a two-part job: blocking creation when a limit is hit, and displaying current usage to workspace admins so they know when they’re approaching a limit and need to upgrade.
The Seat Limit Pattern
Record Limit Enforcement
Feature Flags: Gating Features by Plan
Beyond numeric limits, some features should only be accessible on certain plans: API access, advanced exports, SSO, audit logs. Store these as a list of text feature identifiers on the Plan data type, and check membership in that list before showing any feature.
Building the Usage Dashboard for Admins
Seat Usage Meter
Show seats_used / plan’s seat_limit as a progress bar. Colour it amber at 80%, red at 100%. Link directly to the invite page from the meter.
Record Count
Show current record count vs. plan limit for each major data type. Use a server-side search count, not client-side filter. Cache in a custom state on page load to avoid redundant queries.
Next Billing Date
Store and display the subscription renewal date from the Stripe webhook payload. Show alongside the current plan name, monthly cost, and a link to the Stripe Customer Portal for payment method management.
Upgrade Prompts
When any limit is at 80%+ or a locked feature is accessed, show contextual upgrade prompts in-app. These are your highest-converting upgrade moments — far more effective than a pricing page visit.
Billing History
Use the Stripe API Connector to list invoices for the workspace’s Stripe Customer. Display invoice date, amount, and a link to the Stripe-hosted PDF. Never store payment card details in Bubble.
Trial Countdown
If subscription_status = Trialing, show a prominent trial expiry countdown. Make the trial end date and remaining days visible in the header or sidebar on every page during the trial period.
Workspace Onboarding & First-Run Experience
The onboarding flow is one of the highest-leverage surfaces in your entire SaaS product. It is the moment when a user either understands your product and becomes activated, or gets confused and churns silently. A well-designed Bubble onboarding flow guides new workspace owners through exactly the steps they need to take to reach their first “aha moment” with your product.
The Post-Signup Onboarding Flow
Immediately after email/password signup, redirect to a workspace creation page — not to the main app. Collect workspace name, optionally slug (auto-generated from name), and upload logo. Create the Workspace record, create the first Membership (role = Owner, status = Active), set User’s current_workspace, then start the trial.
A multi-step onboarding checklist page that walks the owner through 3–5 essential setup steps. Store completion state as yes/no fields on the Workspace or User record. Show a progress bar. Each completed step triggers the next one to become active.
Profile setup
Add display name, profile photo, and notification preferences. Store on User record.
Invite first teammate
Prompt to send the first invite. Products with multi-user activation have dramatically better retention.
Create first record
Guide the user to create their first Project, Contact, or whatever the core entity is in your product.
Connect integrations
If your product connects to external tools, this is where to prompt that setup. One integration connected = 40% higher retention.
Define the specific moment when a user has experienced enough of your product to understand its core value. In Asana: “complete your first task.” In Slack: “send a message in a channel with a teammate.” Build your onboarding flow to drive every new user to that moment within the first session. Track it as an event in your analytics system. Users who reach the aha moment in session 1 retain at 3–5× the rate of those who don’t.
The Workspace Switcher
Users who belong to multiple workspaces need a way to switch between them without logging out. The workspace switcher is a dropdown in the app header that shows all workspaces the current user is an active member of, and switches context instantly.
Production Launch Checklist & Security Hardening
Before your multi-tenant SaaS goes live, work through this comprehensive checklist. Every item here represents a failure mode we’ve seen in real Bubble SaaS products. A single missed item can result in a data breach, a billing failure, or a broken user experience for paying customers.
🔒 Data Isolation & Privacy
- ✓Every data type has a privacy rule — no type is left on “Everyone”
- ✓Every app data type has a workspace field populated on creation
- ✓Every search in every workflow and page uses a workspace constraint
- ✓Privacy rules tested with two separate test accounts in different workspaces — confirm Account A cannot see Account B’s data
- ✓User data type privacy rule: users can only see other users who share a workspace with them
- ✓Audit log is restricted to Admin and Owner roles only
- ⚠File uploads: confirm uploaded files are associated with workspace and not publicly accessible via direct URL
👥 Role & Permission System
- ✓Every destructive workflow has a server-side role check (Step 1: Only when) — not just UI-level button hiding
- ✓Owner role is non-transferable without explicit “Transfer Ownership” workflow that includes confirmation
- ✓Workspace deletion requires Owner role AND explicit confirmation (typed workspace name)
- ✓Member removal removes their Membership record AND decrements seats_used on Workspace
- ✓Viewer role correctly blocked from all create/edit/delete workflows, not just UI elements
💰 Billing Integrity
- ✓Stripe webhooks validated with signature verification on every event
- ✓All six critical webhook events handled (checkout, updated, deleted, failed, trial_will_end, payment_succeeded)
- ✓Post-checkout redirect does NOT update subscription status — only webhook updates it (redirect can be spoofed)
- ✓Cancelled workspaces have read-only access, data preserved for 30 days
- ✓Seat limits enforced both in UI and in server-side invitation workflow
- ✓Record limits enforced both in UI and in server-side creation workflows
- ⚠Tested plan downgrade path: workspace exceeding new plan limits shows degraded state, not error
✉ Invitation System
- ✓Invitation tokens are cryptographically random (not sequential IDs, not guessable)
- ✓Invitations expire after 7 days — expired invitations cannot be accepted
- ✓Accept workflow validates that accepting user’s email matches invitation email exactly
- ✓Tested both paths: existing user accepts, new user signs up and accepts
- ✓Duplicate invitation guard: check for existing active Membership before creating another
- ✓Admin can revoke pending invitations before they are accepted
⚡ Performance & Scale
- ✓Every search uses database-level constraints, never client-side :filtered by
- ✓Large lists paginated (page size 15–25, load more on scroll)
- ✓Frequently-accessed counts (seats_used, record_count) stored as denormalised fields on Workspace, updated on change
- ✓Static data (plan names, feature flags) stored in Option Sets, not database types
- ✓Dashboard load time tested with 500+ records in workspace — under 2 seconds
- ✓Bubble app on at least Growth plan for dedicated server capacity (not shared Starter infrastructure)
Recommended Bubble Plugins for Multi-Tenant SaaS
| Plugin / Tool | Use Case | Notes |
|---|---|---|
| Stripe.js by Zeroqode | Stripe payment elements, card input, Customer Portal redirect | Preferred over raw API Connector for Stripe card UI components |
| API Connector (built-in) | Stripe API calls, SendGrid, Slack, any REST integration | Use for all webhook payloads and API calls not covered by plugins |
| SendGrid plugin / API | Transactional emails: invitations, billing alerts, welcome series | Prefer dynamic templates for invite and billing emails; easier to iterate |
| Toolbox plugin | Run JavaScript in workflows, generate UUIDs, execute arbitrary JS | Essential for generating secure random tokens for invitations |
| Air Date/Time Picker | Date inputs with timezone awareness | Multi-tenant SaaS often has users across timezones — handle dates carefully |
| Intercom / Crisp plugin | In-app customer support chat, user identification | Pass workspace ID and plan as user attributes for segmented support |
| Segment / Mixpanel plugin | Product analytics, funnel tracking, feature usage | Track workspace_id as a group property for workspace-level analytics |
| Postmark / Mailgun plugin | Reliable transactional email delivery alternative to SendGrid | Postmark has better delivery rates for invitation and billing emails |
Build Your Multi-Tenant SaaS the Right Way
Architecture reviews, data model design, Stripe integration, and full SaaS builds —
the same disciplined approach applied to every Bubble product we ship.