Search & Filter Performance

Hi Bubblers,

Looking into ways to optimise our app and our uses of search and filtering.

I understand search happens on the serverside while filtering is done locally.

In a scenario where we have a large list of Things that need to be filtered based on the tab a user is currently on, is it better to apply a different search with a constraint for each tab, or to first load the data into a ‘master’ search without the constraint and then apply a filter on the master list for each tab ?

I also observed that when applying a filter on the data from a repeating group that has already been loaded, a new pair of msearch/bulk_watch requests are made, which I don’t understand since the filtering is supposed to apply on a list already made available locally ?

Thanks all for your insight!

Only advanced filtering happens client-side. You can easily check it via Chrome dev tools :slight_smile:

1 Like

Thanks @artemzheg ,

does it mean that these both these configurations happen on the server side and have basically the same performance cost/impact? (Considering that in the second image, there’s no constraint on the ‘search for…’ part).

Thanks for your help!

First one is faster and costs less WU because it does the search server side and then returns only the results you want. Hence you load less data.

Second one returns everything within the constraints of your privacy settings and then filters the search results client side. So you load more data and then add the client-side overhead for the filtering.

As a general rule i avoid putting a search as a data source and opt to put data into a state.

Here’s something i posted that you may be interested in:

1 Like

That should be true only if you are using advanced filtering or if you have something between do a search and :filtered
But if it’s not the case (as in OPs example above) - the number of searches and fetched items should be the same as I remember .

1 Like

All :filtered operations run client-side and apply after the search. The final results are the same but the search returns more data.

You can check this in the debugger and the browser inspector.

From the manual:

…:filtered
Filters a list of things with a criteria. It’s similar to a search but happens after the search and can also be used on a field that is a list of things. The filtering constraints work similarly to a search constraint.

I personally avoid using :filtered until I need advanced filtering to compare lists and remember that Bubble states :filtered is performed after the search (aka client-side). But somehow not long ago while testing one of my apps I’ve discovered that it’s not always true (or I am missing something).

So, I have 4048 cats in my DB. Only 11 cats are relevant for my constraint (age < 10). This 11 cats are distributed among first 300-400 rows of the DB.
I’ve tested with 2 approaches:

  1. Constraint within Do a search expression:

  2. Applying :filtered operator and adding constraint there:

Both approaches resulted in the same amount of requests performed and data fetched (results from Chrome Dev Tools)

Would this be roughly the same as changing the data source via conditionals (rather than conditionally switching the state and keeping data source / searches in the states)?

Bubble has a number of quirks like what you showed and workarounds like copy pasting expressions into privacy conditions. They may work but relying on them is not a good practice.

It’s best to explain documented practices cause new Bubblers might misunderstand it as a feature and then get confused when things go wrong.

1 Like

I make it a practice to only use states as RG data sources, so I know that performance is great even for large data sources.

It’s been a while since I’ve used a search as a data source in an RG but one can assume that each time your RG switches data sources from one search to another that the first time the data source is called, there will be a load time but subsequently it’ll be much faster cause the results have already been loaded and cached by Bubble.

The difference I do know is that there’s a WU overhead for Real-time Search for every active data source using a search.

Thank you all for your insights.

Based on my recent experiments, the :filter does happen on the server side indeed and did trigger a request when I applied it on the already loaded content of a repeating group.

This validates the comment from @artemzheg , which also aligns with what I had read in the book “the ultimate guide to bubble performance” relating to client-side vs. server-side operations.

I’ve just created a bug report to get some insights from Bubble team about :filtered being applied server-side. May be that our test scenarios somehow are not good or not completely relevant.

1 Like

Thanks! Please keep up informed when you recevie an update. :slight_smile:

:filtered always happens server side except if “Advanced:” is used

That’s what we are trying to figure out)
Bubble official documentation and most part of the community (including OGs with tons of experience) states that :filtered is always applied client side after the search.
I was in the same boat for a long time but a random experiment I’ve performed not long ago resulted in :filtered being applied server side (excluding Advanced filtering which is still client side).

So now I’m looking forward to get a reply from Bubble support.

1 Like

Btw, here is an interesting quote from Petter (author of “The Ultimate Guide to Bubble Performance” book):

Thanks for posting! The difference that you bring up about :filters being performed server-side/client-side was one of the major revisions of the second edition of the book, and if that’s the version you’re referring to it may not be clear enough still (I can’t check the book right now, but thanks for including page numbers).

In the first edition, filters were described as being performed client-side more or less without exception, but it should have been made clear that this will normally only apply to advanced filters (or filters applied to an already completed search). Whenever a :filter is applied to a fresh search Bubble will attempt to perform the full query on the server and in many (probably most) cases it can.
[source]

So it would be great if @petter could confirm if it’s still a thing.

1 Like

So, I was lucky enough to get some quick communication with Bubble App Design team support member within an bug report.

The short conclusion is - basic filtering (using almost all options available inside :filtered operator except Advanced...) is performed:

  1. server-side: if it is a part of data fetching (for example, if it is a part of Do a search for:filtered expression when we are expecting to get some data from the database)
  2. client-side: if we are filtering data that has been already fetched beforehand (for example, if we have a custom state that has been already populated with data from the database and we are referencing it in a repeating group with an expression like Custom State:filtered).

So this fully matches information from Petter’s post I’ve mentioned in my previous post above.

7 Likes

Thanks for sharing @artemzheg Looks like i was mostly wrong about the :filtered operator. Would make sense since i don’t use it for basic constraints anymore.

Curious if adding and advanced constraint makes it completely client side or does it pass the basic filters into the search and then run the advanced filters client side