Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to Optimize Database Queries and Performance in Bubble

Slow database queries are the most common performance bottleneck in Bubble apps. This tutorial covers how to speed up Do a Search For operations by using database constraints instead of client-side filters, paginating repeating groups, caching frequently used search results in custom states, and eliminating nested searches that multiply query costs.

What you'll learn

  • How to identify slow database queries using Bubble's performance tools
  • How to replace client-side filters with server-side constraints
  • How to cache search results using custom states to reduce repeated queries
  • How to paginate repeating groups for faster rendering
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read20-30 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

Slow database queries are the most common performance bottleneck in Bubble apps. This tutorial covers how to speed up Do a Search For operations by using database constraints instead of client-side filters, paginating repeating groups, caching frequently used search results in custom states, and eliminating nested searches that multiply query costs.

Overview: Database Query Optimization in Bubble

This tutorial is for Bubble builders experiencing slow page loads or sluggish repeating groups. You will learn why Bubble apps slow down as data grows and the specific techniques to fix query performance. The focus is on actionable changes you can make in the visual editor without plugins or custom code.

Prerequisites

  • A Bubble app with at least one Data Type containing 100+ records
  • Basic understanding of Do a Search For and Repeating Groups
  • Access to your Bubble app's Logs tab for performance monitoring
  • Familiarity with Bubble's Workflow and Design tabs

Step-by-step guide

1

Identify slow queries using the Logs tab and Debugger

Open your Bubble editor and click the Logs tab in the left sidebar. Look at the Server logs section — each entry shows the workflow or page load action, the time it took, and the workload units consumed. Sort by duration to find the slowest operations. Next, preview your app and activate the Debugger by clicking the bug icon in the bottom-right. Step through page loads and workflow actions to see which searches take the longest. Also check Settings → App Metrics to see which pages and actions consume the most WUs over time. Write down the top 3-5 slowest searches to prioritize your optimization work.

Pro tip: Server log retention varies by plan — Free gives only 6 hours. Check logs regularly or upgrade for longer retention.

Expected result: You have a list of your slowest database queries with their execution times and WU costs.

2

Replace client-side filters with database constraints

Find any Do a Search For that uses the :filtered operator after the search. This operator downloads all matching records to the browser first, then filters them client-side — extremely slow for large datasets. Move those filter conditions into the search constraints instead. Click on your Do a Search For, and in the constraints area, add conditions that match what your :filtered was checking. For example, change 'Do a Search for Products:filtered (Category = Shoes)' to 'Do a Search for Products' with a constraint 'Category = Shoes'. Database constraints run on the server and use indexes, making them dramatically faster.

Pro tip: Bubble's text search constraints only index the first 256 characters. For longer text searches, create a separate short text field optimized for searching.

Expected result: Searches that previously used :filtered now use database constraints, resulting in faster query times and lower WU consumption.

3

Eliminate nested searches inside repeating groups

Open your Design tab and check your Repeating Groups. Click on elements inside each cell and look for any that have their own Do a Search For as a data source. A search inside a repeating group cell runs once per visible row — if you show 20 items and each cell has a search, that is 20 separate database queries on every page load. Fix this by pre-computing the data. For example, if each Product cell searches for its review count, add a 'review_count' number field to the Product Data Type. Use a backend workflow to update this count whenever a review is created or deleted. Then display the field directly instead of running a search.

Pro tip: Use the parent group's data reference instead of a separate search. If a cell's parent group is type Product, use Parent group's Product's field directly.

Expected result: Repeating group cells display data from fields on the parent record rather than running individual searches, reducing queries from N to 1.

4

Paginate repeating groups to limit data loading

Select your Repeating Group element and check its layout. If it shows all records at once with no fixed number of rows, it forces Bubble to load every matching record. Change the Repeating Group to a fixed number of rows — 10 to 20 is optimal. Add pagination controls below the group: a Next button and a Previous button. Create a custom state on the page called 'current_page' of type number with a default of 1. Set the Repeating Group's data source to Do a Search for your type with items from calculated offset. The Next button increments current_page and Previous decrements it.

Expected result: The repeating group loads only 10-20 records at a time, with working Next and Previous pagination buttons.

5

Cache search results in custom states

If the same search is used by multiple elements on a page, running it multiple times wastes WUs. Instead, store the result once. Create a custom state on your page element: click the page in the Element Tree, then click the 'i' icon to add a custom state. Name it 'cached_products' with type Product and check 'is a list'. In a Page is loaded workflow, add a Set State action: set page's cached_products to Do a Search for Products with your constraints. Then point your Repeating Group's data source to page's cached_products and your count text to page's cached_products:count. Now one search serves multiple elements.

Pro tip: Custom states reset on page reload. For data that changes rarely, this is efficient. For frequently changing data, direct searches may be preferable since they auto-update.

Expected result: Multiple elements share a single cached search result, reducing the total number of database queries per page load.

6

Use Option Sets instead of database searches for static data

Identify any searches that retrieve data that rarely changes — categories, status labels, countries, or configuration values. These are better stored as Option Sets because they are cached as part of your app's code and require zero database queries and zero WUs. Go to the Data tab, click Option sets, and create a new Option Set. Add options and attributes for any extra data like icon or display_order. Then replace your search-based dropdowns and filters with Option Set references.

Expected result: Static reference data loads instantly from Option Sets with zero database queries and zero WU cost.

Complete working example

Workflow summary
1DATABASE QUERY OPTIMIZATION SUMMARY
2=====================================
3
4DIAGNOSTICS:
5 Logs tab Server logs Sort by duration
6 Settings App Metrics WU breakdown
7 Debugger Step through page loads
8
9OPTIMIZATION 1: CONSTRAINTS OVER :filtered
10 Before: Do a Search for Products:filtered (Category = X)
11 After: Do a Search for Products [Category = X]
12 Why: Constraints use server indexes, :filtered downloads all
13
14OPTIMIZATION 2: NO NESTED SEARCHES IN RG CELLS
15 Before: Each cell runs Do a Search for Reviews:count
16 After: Product has review_count field
17 Backend workflow updates count on create/delete
18 Cell shows Parent group's Product's review_count
19 Why: Reduces N queries to 1
20
21OPTIMIZATION 3: PAGINATE REPEATING GROUPS
22 Repeating Group: Fixed rows = 10-20
23 Custom state: page current_page (number)
24 Data source: Do a Search with offset
25 Next: current_page + 1
26 Previous: current_page - 1 (Only when > 1)
27
28OPTIMIZATION 4: CACHE WITH CUSTOM STATES
29 Custom state: page cached_list (Type, list)
30 Page is loaded:
31 Set state = Do a Search for Type
32 All elements use: page's cached_list
33 Why: One search serves multiple elements
34
35OPTIMIZATION 5: OPTION SETS FOR STATIC DATA
36 Data tab Option sets New Option Set
37 Replace DB searches with Option Set references
38 Why: Zero queries, zero WUs, cached client-side
39
40PERFORMANCE BENCHMARKS:
41 :filtered on 1,000 records 5-15 sec delay
42 Nested search in 20-row RG 20x query cost
43 Unpaginated RG with 500+ items memory issues
44 Option Set vs DB search 100% WU savings

Common mistakes when optimizing Database Queries and Performance in Bubble

Why it's a problem: Using :filtered instead of search constraints for simple conditions

How to avoid: Move filter conditions into Do a Search For constraints wherever possible

Why it's a problem: Running Do a Search For inside repeating group cells

How to avoid: Pre-compute values as fields on the parent Data Type using backend workflows

Why it's a problem: Displaying all records in a repeating group without pagination

How to avoid: Set a fixed number of rows (10-20) and implement pagination using custom states

Why it's a problem: Using database types for static reference data like categories

How to avoid: Convert static, developer-managed data from Data Types to Option Sets

Best practices

  • Use the Logs tab regularly to monitor which queries consume the most WUs
  • Always prefer database constraints over :filtered for better performance
  • Paginate repeating groups to 10-20 items rather than loading all records
  • Pre-compute aggregate values as fields rather than calculating on display
  • Cache frequently used search results in custom states to avoid duplicate queries
  • Use Option Sets for any data that does not change per user or require Privacy Rules
  • Add a search_key text field for searchable content exceeding 256 characters
  • Profile performance before and after changes to verify improvements

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

My Bubble app has a repeating group showing 500+ products and it takes 10 seconds to load. Each cell displays a review count using a separate search. How do I optimize this to load in under 2 seconds?

Bubble Prompt

Help me optimize my product listing page. The repeating group is slow because it loads all products at once and each cell searches for review counts. I want pagination and pre-computed review counts.

Frequently asked questions

Why is my Bubble app so slow?

The most common causes are: searches using :filtered instead of constraints, nested searches inside repeating group cells, loading too many records without pagination, and unused plugins adding overhead. Start by checking your Logs tab.

How many records can Bubble handle before slowing down?

Bubble starts showing noticeable slowdowns around 30,000-50,000 records without optimization. With proper constraints, pagination, and pre-computed fields, apps can handle hundreds of thousands of records.

Do constraints cost fewer WUs than :filtered?

Yes. Constraints run server-side using database indexes and typically cost 0.2-1 WU. The :filtered operator downloads all records first then filters client-side, which is both slower and more expensive.

Should I always use custom states to cache searches?

Not always. Direct searches auto-update in real-time when data changes. Cached custom states do not auto-update. Use caching for data that does not change frequently or where the same search is referenced by multiple elements.

What is the maximum number of items for a repeating group?

For best performance, show 10-20 items per page with pagination. Bubble does not virtualize lists, so every item is rendered in the DOM regardless of visibility.

Can RapidDev help optimize my Bubble app's performance?

Yes. RapidDev specializes in Bubble performance optimization including database restructuring, query optimization, and workload unit reduction for apps experiencing slowdowns.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.