Bubble's data model uses custom Data Types (tables) with Fields (columns) and Things (rows). You create relationships by setting a field's type to another Data Type, supporting one-to-one, one-to-many (list field), and many-to-many patterns. Understanding how to structure types, reference related data in expressions, and use Privacy Rules is essential for every Bubble app.
Work with Dynamic Data Types in Bubble
This tutorial explains Bubble's data model — how to create types, define relationships, and use them throughout your app. Understanding data types is foundational to building any Bubble application.
Prerequisites
- A Bubble account with an active app
- Basic understanding of databases (tables, rows, columns concept)
- Familiarity with the Bubble editor
Step-by-step guide
Create Custom Data Types
Create Custom Data Types
Go to Data tab → Data types → click 'New type'. Name it descriptively (e.g., 'Project'). Add fields: name (text), description (text), status (text), due_date (date), budget (number), is_active (yes/no). Each field has a type: text, number, date, yes/no, file, image, geographic address, or another Data Type. Check 'This field is a list' for fields that hold multiple values.
Expected result: A new Data Type exists with multiple fields of different types.
Set Up Relationships Between Types
Set Up Relationships Between Types
Relationships connect Data Types. One-to-one: add a field 'manager' of type User on Project — each project has one manager. One-to-many: add a field 'team_members' of type User as a list on Project — each project has many members. Many-to-many: create a join type 'ProjectMembership' with fields project (Project) and member (User). Choose the pattern based on your needs.
Pro tip: For one-to-many with under 100 items, list fields work well. For larger relationships or when you need metadata on the relationship, use a join Data Type.
Expected result: Data Types are linked through relationship fields.
Reference Related Data in Expressions
Reference Related Data in Expressions
In the Design tab, you can chain references through relationships. For example: 'Current Page Project's manager's email' traverses from Project → User → email. In a Repeating Group of Projects, each cell can show 'Current cell's Project's team_members:count' for the team size. Use ':first item', ':last item', and ':each item's [field]' operators to work with list fields.
Expected result: Dynamic expressions traverse relationships to display related data.
Search and Filter by Related Data
Search and Filter by Related Data
Use 'Do a Search for' with constraints on related fields. Example: Search for Projects where manager = Current User returns projects managed by the logged-in user. For list fields, use 'contains' as the constraint type: Search for Projects where team_members contains Current User. Combine multiple constraints for complex filters.
Expected result: Searches filter data based on relationships between types.
Set Privacy Rules for Each Data Type
Set Privacy Rules for Each Data Type
Go to Data tab → Privacy. For each Data Type, create rules controlling who can find and view records. Example: for Project, add a rule 'When Current User is in This Project's team_members' with permissions to Find in searches and View all fields. This ensures users only see projects they belong to.
Expected result: Privacy Rules restrict data access based on user relationships.
Complete working example
1DATA ARCHITECTURE EXAMPLE: Project Management App23DATA TYPES:4- User (built-in)5 - name (text)6 - role (text)7 - avatar (image)89- Project10 - name (text)11 - description (text)12 - status (text: active/completed/archived)13 - manager (User) — one-to-one14 - team_members (list of Users) — one-to-many15 - created_date (date)16 - due_date (date)1718- Task19 - project (Project) — many-to-one20 - title (text)21 - assignee (User) — one-to-one22 - status (text: todo/in-progress/done)23 - priority (number)24 - due_date (date)2526- Comment27 - task (Task) — many-to-one28 - author (User)29 - content (text)30 - created_date (date)3132RELATIONSHIP PATTERNS:33- Project → User (manager): one-to-one34- Project → User (team_members): one-to-many via list35- Project → Task: one-to-many (Task has 'project' field)36- Task → Comment: one-to-many (Comment has 'task' field)37- Task → User (assignee): one-to-one3839EXPRESSION EXAMPLES:40- Current Page Project's manager's name41- Current Page Project's team_members:count42- Search for Tasks (project = Current Page Project):each item's status43- Current cell's Task's project's nameCommon mistakes when workking with dynamic data types in a Bubble.io app: Step-by-Step Guide
Why it's a problem: Using text fields for relationships instead of Data Type references
How to avoid: Always use a field typed as another Data Type for relationships, not text fields storing IDs or names.
Why it's a problem: Creating deeply nested relationships (4+ levels)
How to avoid: Flatten your data model by adding direct references where needed, or denormalize by copying frequently accessed data.
Why it's a problem: Not setting Privacy Rules on new Data Types
How to avoid: Create Privacy Rules immediately after creating a new Data Type.
Best practices
- Name Data Types as singular nouns (Project, not Projects) for clarity in expressions.
- Use list fields for small collections (under 100 items) and separate join types for larger relationships.
- Add Privacy Rules to every Data Type immediately after creation.
- Use Option Sets for static categories instead of Data Types for better performance.
- Document your data model — Bubble has no built-in schema diagram, so maintain one externally.
- Avoid circular references (A references B which references A) as they complicate Privacy Rules.
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm building a project management app in Bubble.io. I need Data Types for Projects, Tasks, and Comments with proper relationships. How should I structure the data model, set up relationships (one-to-one, one-to-many), and configure Privacy Rules?
Create Data Types for Project (with manager and team_members), Task (linked to Project and assignee User), and Comment (linked to Task). Set up Privacy Rules so users only see projects they belong to.
Frequently asked questions
What is the difference between a Data Type and an Option Set?
Data Types store dynamic, user-generated data in the database. Option Sets store static, developer-defined data in the app source code. Use Option Sets for categories, statuses, and labels that do not change. Use Data Types for user content.
Can I change a field's type after creating it?
No. You must delete the field and create a new one with the correct type. Deleting a field does not remove the underlying data immediately, but you lose access to it in the editor.
How many Data Types can I create?
Bubble supports up to 1,000 custom Data Types per app. Most apps use 10-30 types.
What happens when I delete a Data Type?
All records of that type are deleted. Any elements, workflows, or expressions referencing it will break. The Issue Checker will flag these broken references.
How do I handle many-to-many relationships?
Create a join Data Type. For example, ProjectMembership with fields 'project' (Project) and 'user' (User). Search for ProjectMemberships to find all users in a project or all projects for a user.
Should I denormalize data for performance?
Sometimes. Storing frequently accessed computed values (like task count on Project) avoids expensive searches. For complex data modeling, RapidDev can help design an optimized schema for your use case.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation