Bubble Migration Performance Testing: Set a Baseline Before Rebuilding
Before rebuilding a Bubble app, benchmark the user journeys your business depends on. Record how long they take, whether they finish correctly, and how they behave under representative traffic. Repeat those tests on the coded application with comparable data, permissions, devices, and cache conditions. Agree on acceptance criteria before reviewing the results.
That gives a founder or CTO something concrete to approve. “The new dashboard feels faster” becomes “the largest customer account can load its orders, change a filter, and open an order within the agreed limits, with the correct permissions.”
A migration changes too many things to make an undocumented before-and-after comparison useful. A small, repeatable benchmark makes those differences visible.
Choose journeys that represent the working product
Start with a short list of important tasks. For a business application, that might include opening an account dashboard, searching a large collection, saving a record, and generating a report. Include a frequently used journey and an expensive one that runs less often but matters when it does.
Give each test an exact start and finish. “Search performance” is vague. “From submitting a filter to seeing the correct first page of results” is measurable. Specify result count, sort order, and pagination so the rebuilt version cannot appear faster simply by returning less useful information.
Include the conditions that make your app difficult:
- A new account, a typical account, and a large account
- Ordinary members, account owners, and relevant restricted roles
- Realistic relationships, attachments, long text fields, and uneven record distribution
- Common searches, empty results, and filters that match many records
Use synthetic or appropriately sanitized data that preserves those characteristics. A million records spread evenly across tenants may exercise the system differently from one large customer holding most of them. Keep authorization active throughout the benchmark; an administrator-only test does not represent an ordinary member’s experience.
Bubble’s performance guidance explains how fetched data, query structure, and page complexity affect performance. Record those characteristics rather than treating total database size as the whole test.
Measure the page, the interaction, and the completed task
Different measurements answer different questions. Keep three views in the report.
Browser experience
Core Web Vitals cover loading, responsiveness, and visual stability through Largest Contentful Paint, Interaction to Next Paint, and Cumulative Layout Shift. They are useful for identifying a page that paints slowly, responds poorly, or shifts while someone uses it. Core Web Vitals are assessed at the 75th percentile; keep that assessment separate from any p95 journey target you set for migration acceptance.
Add application-specific timing. A dashboard can display its main heading while its essential data is still loading. Define “dashboard ready” as a visible, usable state with the expected information. For search, measure until the correct results appear, not just until a loading indicator replaces the button. Use browser automation or application instrumentation to time that usable state, alongside protocol-level load generation where appropriate.
Request behavior
Record request duration and failures to help locate delays. Be precise about the tool: k6’s HTTP request duration includes sending, waiting, and receiving, but excludes initial DNS lookup and connection establishment. It also does not include rendering the result in the browser.
Do not require the old and new applications to make identical requests. Their implementations will differ. Compare the same user outcome, then use request-level measurements to explain it.
Business completion
For an export, measure until the correct file is available. For a save, confirm the updated value persists and appears on a subsequent read. A successful HTTP status alone does not establish either outcome.
Keep correctness checks beside timing results. Missing rows, stale data, and unauthorized results make a fast run unacceptable.
Make the comparison reproducible
Document the Bubble version and environment, the code release, data fixture, browser version, test location, device profile, and network settings. Record infrastructure configuration and relevant third-party dependencies on both sides.
Compare the deployment configurations you actually intend to operate. If staging has fewer resources, a different region, or mocked integrations, make that limitation explicit. Avoid treating a Bubble development preview and a production-optimized code deployment as an unqualified comparison.
Separate first visits from repeat visits
Run a first-visit test with an empty browser cache and a repeat-visit test with warmed browser assets. Label both. Keep the navigation sequence and authentication state consistent; a fresh browser profile can also change cookies, sessions, and local storage.
Browser cache, application cache, and database cache are separate layers. Clearing browser storage does not establish that the server is cold. Record the server-side conditions you can control, and label the others unknown. Do not claim equivalent cold-server tests when you cannot verify them on both systems.
If the rebuild uses cached reports, include an agreed freshness requirement. Compare results for the same business period and check that recent changes appear within that limit.
Repeat runs under the same conditions and retain the individual results. Investigate unusually slow runs instead of silently removing them. If you exclude a run because the test machine failed, record the reason and rerun it.
Report percentiles alongside errors and sample counts
An average can hide a frustrating tail of slow experiences. Report the median, or p50, and a tail measure such as p95 for each important journey. A p95 of three seconds means approximately 95% of measured observations completed within three seconds.
Include the number of observations and the measurement period. A percentile from a handful of attempts gives weak evidence about busy production behavior. Use repeated runs and enough samples to see whether the result is stable; do not present a small test’s p99 as a dependable worst-case guarantee.
Track failed journeys, timeouts, and incomplete work separately. If latency percentiles cover successful journeys only, say so. A faster successful subset can conceal a growing failure rate.
Keep results separated by journey and important conditions. Combining a lightweight page with a heavy report can hide a regression. Similarly, a better overall result may conceal slower behavior for the largest tenant or mobile users.
Test the traffic pattern you expect
Registered users are not a load profile. Describe how many people are active together, what they do, how often they start tasks, and how much time they spend between actions. Include background work that normally overlaps with those actions.
A practical sequence is to validate the script with minimal traffic, test an ordinary busy period, then test an agreed peak. Give each stage a duration and stop conditions, including spending limits for Bubble workload and third-party services. Use an isolated, representative environment where possible, approved test accounts, sandboxed payments, and intercepted notifications. Respect third-party limits and agree on production testing before generating load there.
Choose the load model deliberately. With a fixed number of virtual users, slower responses can cause fewer journeys to start. An arrival-rate model starts journeys at a specified rate independently of earlier completions. The k6 explanation of open and closed models describes this difference.
Record offered traffic, completed journeys, and failures. Check whether the load generator actually sustained the target. k6’s dropped iterations can indicate iterations that never started; investigate them rather than counting them as successful capacity.
Follow asynchronous work through to completion
A quick “report requested” response can hide a long queue. Measure acknowledgement time and end-to-end completion separately. Where instrumentation allows, also record queue wait and processing time.
Bubble documents that scheduled workflows can start after their scheduled time when resources are unavailable. The rebuilt queue needs equivalent scrutiny.
Track each test job with an identifier and check its final output. Count jobs submitted, completed, failed, and still pending at the agreed deadline. After the busy period, observe whether the backlog drains. Do not stop measurement when the load generator finishes submitting work.
For a hybrid Bubble migration, include the full path across both systems. A quick coded endpoint can still leave users waiting for Bubble processing or synchronization.
Write acceptance criteria before the rebuild is judged
The baseline describes the current application. Acceptance criteria describe what the business requires from the replacement. If the current experience is already too slow, matching it may be insufficient.
Use a short record for each journey:
- Journey, business owner, and test owner
- Start event, finish event, and expected output
- Dataset version, account size, role, and permissions
- Device, region, network, cache state, and deployment versions
- Traffic profile, run duration, sample count, and repeated-run results
- Bubble baseline and agreed latency, freshness, and completion targets
- Failure limits, correctness checks, and observed exceptions
- Evidence links, decision, and any required retest
Set targets from user needs and operational constraints. Avoid copying a universal response-time target from a tool’s example. Grafana’s k6 thresholds let engineers turn agreed metric limits into automated pass/fail criteria, including custom measurements.
Keep functional acceptance alongside those thresholds. A passing latency check cannot approve a report with missing data.
Illustrative example: an account’s order dashboard
The following numbers are invented to show the method. They are not client results or recommended targets.
A team benchmarks an order dashboard using a synthetic large-account fixture, a member role, the same filters, and an agreed arrival-rate profile. The timer runs from navigation to a usable first page of 25 correctly sorted orders. Cold-browser and warm-browser runs are separate.
Across repeated cold-browser runs, the Bubble baseline records a p95 of 4.6 seconds. The team agrees before rebuilding that this journey must meet a p95 of 3.0 seconds or less, with all correctness checks passing and an explicitly defined failure limit.
The first coded version records 2.4 seconds, but its fixture omits the account’s archived orders. The comparison is incomplete. After restoring the intended data shape and rerunning the same test, its p95 is 3.3 seconds. Correctness passes, but performance acceptance fails.
The useful result is a specific engineering task: investigate that journey and retest it. The earlier headline number provides no basis for approval.
Confirm the result with real usage after launch
Controlled tests help isolate changes. Real-user measurements show what happens across actual devices, networks, locations, and behavior. Google’s guide to lab and field data explains why these results can differ.
Keep the baseline scripts and measurements after launch. Review equivalent journeys by device, region, role, and account size where your instrumentation supports those segments. Use privacy-safe identifiers and avoid logging sensitive record contents. Compare representative business periods and recurring jobs, with an owner assigned to investigate regressions.
Frequently asked questions
- Is a Lighthouse score enough to approve a Bubble migration?
- No. It helps assess a page under controlled conditions, but a migration also needs authenticated journey timing, correct outputs, permission checks, realistic load, and completed background work. Use it as one part of the evidence.
- Should workload units be part of the benchmark?
- They can be a useful cost measure on the Bubble side. Keep them separate from user-visible latency and successful completion. Our Bubble workload-unit audit covers that investigation in detail.
Sources
- 01Performance guidance · Bubble Docs
- 02Core Web Vitals · web.dev
- 03HTTP request duration · Grafana k6 Docs
- 04K6 explanation of open and closed models · Grafana k6 Docs
- 05Dropped iterations · Grafana k6 Docs
- 06Scheduled workflows can start after their scheduled time · Bubble Docs
- 07K6 thresholds · Grafana k6 Docs
- 08Guide to lab and field data · web.dev
Keep reading
Bubble to Code is an independent service. Not affiliated with, endorsed by, or sponsored by Bubble Group, Inc.
