Slow Bubble apps lose users and waste Workload Units. This tutorial covers the most impactful performance optimizations: reducing database queries, replacing searches with Option Sets, optimizing Repeating Groups, minimizing page weight, and monitoring Workload Unit consumption. Apply these techniques to make your Bubble app noticeably faster without rebuilding anything from scratch.
Overview: Optimizing Bubble App Performance
Performance is the most discussed pain point in the Bubble community. Apps become slow when database queries multiply, Repeating Groups load too many items, pages have too many dynamic elements, and plugins add unnecessary overhead. This tutorial gives you a practical optimization checklist covering database efficiency, workflow optimization, page weight reduction, and Workload Unit monitoring.
Prerequisites
- A Bubble app that you want to optimize
- Access to Settings → Metrics for Workload Unit monitoring
- Basic understanding of Bubble's data architecture (searches, Data Types, Option Sets)
- Familiarity with Repeating Groups and how they load data
Step-by-step guide
Audit your Workload Unit consumption
Audit your Workload Unit consumption
Go to Settings → Metrics (or the Logs tab → Workload metrics). Review the pie chart showing which activities consume the most WUs. Identify the top consumers — common culprits include complex searches, Repeating Groups with nested searches, and backend workflows processing large lists. Click into specific time periods to see spikes. The Server logs tab shows WUs charged per individual action, helping you pinpoint exactly which workflows and searches are most expensive. Focus your optimization efforts on the top 3-5 consumers first.
Pro tip: Check WU consumption during peak usage hours — an app that seems fine with 10 users may struggle with 100.
Expected result: You have identified the top WU consumers and know which parts of your app to optimize first.
Replace searches with Option Sets where possible
Replace searches with Option Sets where possible
Option Sets are cached on the user's device and cost zero Workload Units to access. Any data that is static and does not change per user — categories, statuses, countries, feature flags — should be an Option Set instead of a Data Type. Go to Data tab → Option sets and create sets for your static data. Then update all elements that currently search a Data Type for this static data to reference the Option Set instead. For example, replace 'Do a search for Categories' with 'All Categories' (the Option Set). This eliminates database queries entirely for that data.
Expected result: Static data is served from Option Sets with zero database cost, reducing WU consumption and improving load time.
Optimize Repeating Group performance
Optimize Repeating Group performance
Repeating Groups are the most common performance bottleneck. Apply these fixes: (1) Add pagination — set a fixed number of rows (10-20) instead of showing all items. (2) Use database constraints instead of :filtered — constraints run on the server and use indexes; :filtered processes every row client-side. (3) Remove 'Do a search for' inside RG cells — each cell search multiplies queries by the number of visible cells. Instead, use Parent group's data references. (4) Pre-compute counts — if you show 'Number of comments' per post, add a Comment_Count field to the Post type and increment it in workflows instead of counting dynamically.
Pro tip: A Repeating Group showing 20 items with 3 searches per cell generates 60 database queries on every load. Replacing those with Parent group references reduces it to 1 query total.
Expected result: Repeating Groups load faster with fewer database queries through pagination, constraints, and parent data references.
Reduce page weight and element count
Reduce page weight and element count
Bubble renders every element when the page loads, even hidden ones. To reduce page weight: (1) Remove unused elements — check the Element Tree for elements you no longer need. (2) Move complex sections into Reusable Elements — they load on demand. (3) Uninstall unused plugins — every plugin adds JavaScript to every page regardless of use. Go to Plugins tab and remove any you are not actively using. (4) Compress images — use tools like TinyPNG before uploading. Bubble's image auto-compression helps but pre-compression is better. (5) Minimize the number of groups and nested containers — flatten your layout where possible.
Expected result: Pages load faster with fewer elements, no unused plugins, and optimized images.
Optimize workflows and backend processing
Optimize workflows and backend processing
Move expensive operations to backend workflows where they do not block the user interface. Use 'Schedule API Workflow' to process heavy tasks asynchronously — the user sees a confirmation immediately while processing happens server-side. For bulk operations, use 'Schedule API Workflow on a list' instead of looping. Eliminate redundant workflow actions — if two actions write to the same record, combine them into one 'Make changes to a thing.' Remove 'Add a pause before next action' workarounds and use 'Result of step X' for data dependencies instead.
Pro tip: For apps with significant performance challenges, RapidDev can conduct a full performance audit identifying the specific bottlenecks and implementing targeted optimizations to reduce WU consumption and improve load times.
Expected result: Expensive operations run asynchronously in backend workflows without blocking the user interface.
Implement caching strategies
Implement caching strategies
Store frequently accessed data in Custom States or hidden floating groups to avoid repeated searches. On page load, run your heavy searches once and store results in a Custom State — subsequent references use the cached state instead of re-querying. For data that multiple users access (like a leaderboard), consider a CachedData Data Type that stores pre-computed results with a timestamp. A scheduled backend workflow refreshes this data periodically. Users read from the cached record instead of running the expensive query on every page load.
Expected result: Frequently accessed data is cached, reducing redundant database queries and improving response times.
Complete working example
1PERFORMANCE OPTIMIZATION — CHECKLIST2======================================34DATABASE OPTIMIZATION:5 [x] Replace static Data Type searches with Option Sets6 [x] Use constraints instead of :filtered on searches7 [x] Remove 'Do a search for' inside Repeating Group cells8 [x] Pre-compute counts/aggregates as fields (not dynamic)9 [x] Use 'Result of step X' instead of re-searching10 [x] Paginate Repeating Groups to 10-20 items1112PAGE WEIGHT REDUCTION:13 [x] Remove unused elements from Design tab14 [x] Uninstall unused plugins from Plugins tab15 [x] Compress images before uploading (TinyPNG)16 [x] Move complex sections to Reusable Elements17 [x] Flatten nested groups where possible18 [x] Use Collapse when hidden on conditional elements1920WORKFLOW OPTIMIZATION:21 [x] Move heavy processing to backend workflows22 [x] Use Schedule API Workflow on a list for bulk ops23 [x] Combine multiple writes to same record into one action24 [x] Remove unnecessary 'Pause before next action'25 [x] Use Custom Events for sequential dependencies2627CACHING:28 [x] Store search results in Custom States on page load29 [x] Use hidden floating groups for frequently accessed data30 [x] Create CachedData records for shared expensive queries31 [x] Refresh caches with scheduled backend workflows3233MONITORING:34 Settings → Metrics → Workload metrics35 - Review top WU consumers36 - Check peak usage periods37 - Monitor per-action WU costs in Server Logs38 - Set alert thresholds at 75% of plan limitCommon mistakes when optimizing performance of Bubble.io apps: Step-by-Step Guide
Why it's a problem: Using :filtered instead of database constraints on searches
How to avoid: Move filter logic into search constraints wherever possible. Only use :filtered for conditions that cannot be expressed as constraints.
Why it's a problem: Nesting 'Do a search for' inside Repeating Group cells
How to avoid: Use Parent group's data references or pre-compute related data as fields on the parent Data Type.
Why it's a problem: Keeping unused plugins installed
How to avoid: Go to Plugins tab and remove any plugins your app does not actively use.
Why it's a problem: Loading all items in a Repeating Group without pagination
How to avoid: Set a fixed number of rows (10-20) and add pagination controls or infinite scroll with incremental loading.
Best practices
- Use Option Sets instead of database searches for all static data (categories, statuses, countries)
- Paginate Repeating Groups to 10-20 items and add load-more or pagination controls
- Use database constraints instead of :filtered for server-side filtering with indexes
- Remove unused plugins, elements, and workflows to reduce page weight
- Pre-compute counts and aggregates as fields instead of calculating dynamically
- Move heavy processing to scheduled backend workflows to keep the UI responsive
- Monitor Workload Unit consumption weekly and investigate any unexpected spikes
- Compress all images before uploading to reduce page load time
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
My Bubble.io app is slow and I'm burning through Workload Units. Can you give me a systematic optimization checklist covering database queries, Repeating Groups, page weight, and caching strategies?
Help me optimize a Repeating Group that shows a list of products. Currently each cell runs a search to count reviews. I need to replace this with a pre-computed count field and use Parent group data references instead of per-cell searches.
Frequently asked questions
What is the biggest performance killer in Bubble apps?
Nested searches inside Repeating Group cells. Each cell runs its own database query, multiplying queries by the number of visible cells. Replacing these with Parent group data references is the single highest-impact optimization.
Do Option Sets consume Workload Units?
No. Option Sets are cached in the app's JavaScript on the client side. Accessing them costs zero WUs and is instant. Use them for all static data.
How do I know if my app is slow because of the database or the page?
Check Server Logs for query execution times (database) and use your browser's DevTools Network tab for page load times (frontend). High WU consumption points to database issues; slow page rendering points to too many elements or heavy plugins.
Will upgrading my Bubble plan make my app faster?
Higher plans provide more server capacity, which helps under load. But if your app has inefficient queries or heavy pages, upgrading only masks the problem temporarily. Optimize first, then scale.
Can I use an external database for better performance?
Yes, but external databases add latency because calls route through Bubble's server (5 hops instead of 3). External databases help when you need advanced SQL queries or handle millions of records.
Can RapidDev help optimize my Bubble app's performance?
Yes. RapidDev offers performance audits that identify specific bottlenecks in your app's database queries, page rendering, and workflow efficiency, then implements targeted optimizations to reduce WU costs and improve speed.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation