Bubble.io Repeating Groups: Mastering Lists, Pagination and Performance
Repeating groups are the backbone of most Bubble.io interfaces: product grids, task lists, inboxes, dashboards and search results. They are easy to start with and easy to get wrong, because a list that works well with ten records can become slow and expensive with ten thousand. This guide covers how repeating groups work, how to load data efficiently, how to paginate, and the habits that keep large lists fast.
- How repeating groups work
- Data sources done right
- Search constraints vs :filtered
- Sorting and empty states
- Pagination and infinite scroll
- Nested repeating groups
- Performance checklist
- FAQ
How repeating groups work
A repeating group has a type of content (for example Task) and a data source (for example a search for Tasks). You design a single cell, placing text and buttons that refer to Current cell’s Task, and Bubble.io repeats it for each item. Clicking an element inside a cell gives workflows access to that cell’s item, so you can open, edit or delete it.
Data sources done right
- Do a search for is the usual source; add constraints to return only what the user needs
- A list field on another record, such as a Project’s list of members, is fast when the list stays small
- Option sets are ideal for fixed lists such as categories or statuses, because they need no database search
- Respect privacy rules: repeating groups only show records the current user is allowed to find, so your list is also a test of your security setup; see privacy rules
Search constraints vs :filtered
| Search constraints | :filtered | |
|---|---|---|
| Where it runs | On Bubble.io’s server | After data loads |
| Data transferred | Only matching records | Everything, then filtered |
| Speed and cost | Fast and efficient | Slower and uses more resources |
| Use when | Almost always | Conditions a search cannot express, on small lists |
A good habit: for every condition on a list, ask whether it can be a search constraint first. Optional filters, such as a status dropdown that may be empty, can use the setting to ignore empty constraints, so one search handles every combination.
Sorting and empty states
Sort in the search itself, for example by Created Date descending, rather than sorting afterwards. Always design an empty state: a friendly message and a clear action when there are no items yet, shown with a condition when the list’s count is zero.
Pagination and infinite scroll
Never load thousands of records at once. Choose one of these patterns:
- Fixed rows with pages: show, say, 20 rows, with Next and Previous buttons that move through the list. Best for tables and admin screens
- Scrolling with automatic loading: a vertically scrolling layout that loads more items as the user reaches the bottom. Best for feeds and mobile-style lists
- Load more button: shows the next batch on demand, a good middle ground
Show the total count, such as “Showing 20 of 340”, so users understand where they are.
Nested repeating groups
A repeating group inside another, such as projects with their tasks, multiplies searches: every outer row runs its own inner search. Keep nesting shallow, limit the inner list, and consider storing a short list or summary on the parent record. For heavy reporting views, precompute totals with a backend workflow instead of calculating them in every cell. See Bubble.io database design for data structures that make lists efficient.
Performance checklist
- Conditions are search constraints, not :filtered, wherever possible
- Lists are paginated or load in batches
- No searches inside every cell unless the list is small
- Counts and totals are stored or precomputed for large data sets
- Images are sized appropriately rather than full-resolution
- Option sets are used for fixed lists
- You have tested with realistic data volumes, not just a handful of records
Efficient lists also reduce your workload unit usage; see workload units explained and 7 patterns that make Bubble.io apps fast.
Frequently asked questions
What is a repeating group in Bubble.io?
A repeating group is the element that displays a list of things, such as products, tasks or messages. You give it a type of content and a data source, design one cell, and Bubble.io repeats that design for every item in the list.
Why is my repeating group slow?
The most common causes are using filters instead of search constraints, loading too many items at once, and nesting searches inside each cell. Move conditions into the search itself, limit how many items load, and avoid searches inside every row.
What is the difference between search constraints and :filtered in Bubble.io?
Search constraints run on Bubble.io's server, so only matching records are sent to the browser. The :filtered operator runs after the data has loaded, which means more data is transferred and processed. Use constraints wherever you can.
How do I add pagination to a repeating group?
Use a fixed number of rows and add Next and Previous buttons that show the next or previous set of items, or use a scrolling layout that loads more items as the user scrolls. Both avoid loading the whole list at once.
Can I put a repeating group inside another repeating group?
Yes, but use it carefully. Each inner list runs its own search for every outer row, which can multiply the work quickly. Where possible, store the related items directly on the parent record or restructure the data so fewer searches are needed.
Is your Bubble.io app getting slow?
Book a free Idea Audit. We review data structure, lists and workflows, and show you what to fix first.