Did you know that the order in which you set up your Bubble Conditions affect how well they will perform? In Bubble.io, a Condition is any expression that you set up to provide a yes/no answer, whether you’re doing it on an Element or in a Workflow.
A typical Condition placed on an Element would be to keep it hidden or visible based on some state of the User for example:
You can of course also place the same Condition on a Workflow or Action:
From a performance perspective these two types of Bubble conditions (on elements and in workflows) behave a bit differently: any condition you place on an element will be processed as soon as the element loads – usually when the page loads. Bubble Conditions placed on a workflow or action on the other hand will run when you execute it (unless you deliberately separate the condition and the workflow to speed up your app using process spreading).
No matter where you place it though, there’s a simple physical matter at hand here: some kind of data needs to be processed somehow in order for Bubble to return a yes or no value. That process can sometimes be so fast as to the user not perceiving any delay at all (like the examples above), and other times they’ll bring up the blue loading bar that we all know and love.
Processes like that can happen on the client or on the server, and the latter is often a cause of delay. Let’s look at what that means.
Server-side vs client-side in Bubble conditions
Conditions happening server-side
The easiest way to check if a condition will need to query the server is to ask the following two questions:
- Does the condition rely on information in the database?
- Has that information been loaded yet or not?
Any time you ask Bubble to check something in the database you’ll experience a slight delay. Your browser sends the request to Bubble’s server, the request is fulfilled and the results are sent back. Alas, even if the information travels through state-of-the-art interoptic cables at about a speed of 300 000 km/s (186 000 mi/s), it’s not infinite after all.
So for the first question, we need to determine if we’re touching the database. Let’s set up a condition like the one below:
Since we’re performing a search, we’re telling Bubble to “please check my database using these rules, and send the result back to me”. We’re clearly relying on information on the server here, and can expect a delay.
For the second question, we need to know if the information has already been loaded. How can we tell? We’ll need to ask the question: have we referenced this information anywhere at an earlier point? Take a look at the example below:
In this example, we’re also asking Bubble to check some data in the database for us, again obviously needing information from the server. But, there’s a key difference here: since we’re asking about information that’s already loaded into the Parent element, we don’t need to ping the server again. Voila – the delay is gone. It’s worth noting here though: it’s not actually gone: we’ve just moved it. Bubble loads the information on page load, and when we run our condition, it’s already available to us. This way of thinking about when information loads is the cornerstone of process spreading.
But as always, there are caveats: what if we make a slight change to our condition:
Now we’re asking Bubble to reference the Parent Group’s thing (Product) – all good so far – but then we’re asking form information stored on another sub-Thing (User). This information has not been loaded, and we’re back to having to ping the server for it. What if we reference the Current User:
In this example, the logic tells us that we have to access the database to fetch this information: but we happen to know that information about the Current User is always loaded on page load. If you’re interested in learning more about the exact information Bubble loads on page load, check out our book The Ultimate Guide to Bubble Performance.
Conditions happening client-side
The client is the User’s computer, tablet or phone. Let’s set up another Condition as an example:
In this example, we’re not asking for anything from the database. The element we’re asking about is already loaded, and Bubble obviously knows whether its visible or not, since…. well, it is.
So this Bubble Condition will be processed purely client-side and will be lightning-fast.
The order in which Bubble Conditions are evaluated
In regular programming (or indeed in mathematics), the order of operations is a set of rules that tells us which procedures to perform first in order to correctly evaluate a given expression. This is sometimes called or operator precedence or order of precedence. For example, in mathematics multiplication has a higher precedence than addition, and this is why 5 + (3 × 6) = 23 and not (5 + 3) x 6 = 48. Your teacher imprinted this in your brain sometime during your school years, and you keep that knowledge around to snugly be able to correct someone in a forum discussion once every few years.
Now throw that out of the window.
Bubble evaluates expressions purely from left to right, regardless of any other kind of precedence you might expect, and there’s currently no way to use parentheses to override it. This left-to-right thinking also applies to the order of multiple conditions on one element: left-to-right naturally leads to top-to-bottom, meaning that the last condition in a list will override any one conditions on top of it.
Back to single Bubble Conditions with multiple steps: In July 2021, they made an interesting change to how multi-step Conditional expressions are evaluated: Bubble used to go through all steps in the expression, regardless if it was really necessary or not.
From that change on, Bubble’s engine stops checking the expression as soon as it’s found a definite yes / no answer. Using and/or operators to bind together several steps in a Condition leads us to the following logic:
A and B, but A is false → return false and do not evaluate B.Bubble’s forum post explaining the change.
A or B, but A is true → return true, and do not evaluate B
What does this mean for us? Well, since we now know that some Bubble Conditions take longer to evaluate than others (especially when they require server queries), and we also know that Bubble stops checking an expression if it already has a definite answer, we can draw the lesson that the order in which we set up our Conditions matter. Take a look at the Condition below:
Here we’re asking Bubble to first query our database (server-side operation) and then we’re checking an Element’s visibility (client-side operation). Since we’re binding the two steps together with an or operator, it means that as long as the first step returns the value we want, Bubble doesn’t need to check the second step. In our example here, we can exploit that fact to get a performance gain simply by switching the order of the steps:
If the first step in this expression returns the value we want, Bubble skips the second step and never needs to query the database at all.
With a very small change, we’ve improved the performance of our app ever so slightly – and as we teach in the book: performance is a war of a thousand battles.
Leave a comment if you have questions or feedback, and if this tutorial helped you out, you can consider buying me a coffee or becoming a supporter. For more in-depth and advanced learning about important no-code topics you can also check out our Bubble.io books.