Lookup by slug - longer page load and higher WU cost

I have a page with content type “blog_post”. I’ve noticed that when a blog_post has a slug set, during page load and when setting the page thing, there’s an additional search being executed which costs extra WU and significantly increases page load speed.

This doesn’t happen when the blog_post doesn’t have a slug and the page thing is set using the blog_post id with fetch type mget. In that case, the URL is /post/{id}.

Looks like this is the same issue @matt.n spotted here https://forum.bubble.io/t/lookup-by-slug-vs-id-the-workload-costs/344362. Unfortunately, I couldn’t find any info on the forum about how to avoid this extra search when using slugs to set the page thing.

Is this behavior correct or is this a bug that’s been causing longer page loads and higher WU for at least a year now?

@matt.n @boston85719 @fede.bubble what do you guys think?

Here are my test results: Each time I did 5 page loads with Google Chrome Console > Cache disabled = true.

1. WITH SLUG

COSTS
Workflow Units per page load total: 1.31 WU

Page Load: 0.67 WU
Fetching Data 0.64 WU:

  • Search (x1): 0.52 WU
  • Individual Data Request: 0.12 WU

PERFORMANCE

Network tab (Fetch/XHR) logs:

  • document: 337 ms
  • hi: 271 ms
  • start: 516 ms
  • client_log: 292 ms
  • mget: 318 ms
  • m: 259 ms

Logs related with blog_post search:

  • msearch blog_post: 404 ms
  • bulk_watch: 312 ms

Average LCP: 2.72 s (Above 2.5s means page load speed needs improvement for Google :grimacing:)

2. WITH ID

COSTS
Workflow Units per page load: 0.45 WU (less by 0.86 WU - 66% cheaper :dollar_banknote:)

Page Load: 0.37 (less by 0.3 WU)
Fetching Data 0.08:

  • Search: 0 WU
  • Individual Data Request: 0.08 WU

PERFORMANCE

Network tab (Fetch/XHR) logs:

  • document: 565 ms
  • hi: 372 ms
  • start: 508 ms
  • client_log: 387 ms
  • mget: 362 ms
  • m: 268 ms

Logs related with blog_post search:

  • msearch blog_post: 0 ms
  • bulk_watch: 0 ms

Average LCP: 2.0 s (less by 0.72s - 25%). Below 2.5s means page load speed is Good for Google.

Yeah, what you’re seeing is pretty much how Bubble handles slugs right now. When a page loads with a slug, Bubble does an extra search in the background to figure out which thing the slug belongs to. That extra lookup is what’s adding the extra WU and slowing down your LCP. With an ID, Bubble can skip the search completely and just mget the thing directly, which is why your tests look so much cleaner.

At the moment there isn’t a native way to avoid that extra search when using slugs. A bunch of us have run into the same behavior, and it’s been mentioned before, but Bubble hasn’t optimized it yet.

If performance really matters, the only reliable workarounds are either sticking to IDs for internal traffic or loading the page with the ID first and then rewriting the URL to a slug afterward, kind of hacky, but people do it.

So yeah, this isn’t a bug, it’s just how Bubble handles slugs right now, even though it definitely impacts speed and WU. Hopefully they improve it because your numbers match what others have been seeing.

Thx. That explains a lot.

But to be honest, I don’t really understand why Bubble searches for this object in the database when it already has it passed via ID. What’s the point of that?

Performance is really important for me because the project is a marketplace where users can write and publish content. The content needs to rank for SEO. Content needs to be shareable so URLs have to be SEO and user-friendly.

slug-based routing in bubble always triggers an internal lookup first, which is why you’re seeing that extra search and the higher WU. bubble has to translate the slug back into the actual thing before it can run the mget, so that extra query is baked into how slugs work right now. loading by id skips that step completely, which is why your tests look so much cleaner.

it’s not really a bug, just an implementation detail that ends up hurting performance on heavier pages. the only way around it today is to load the page with the id and then swap the url to the slug after the content is already on the screen. you get the clean url without paying for the slug lookup during the initial load.

until bubble updates how slugs resolve, that’s the only dependable way to avoid the extra search.

Thx @iamcharlesac

But I still don’t get it because when I look at the logs in Chrome console, I can see that “document”, which loads first, already contains the data of my blog_post object. That means it’s already been located and added to the page on the backend. The repeated Search only appears in the console later, after the Bubble js scripts have loaded.

Also a question about that hack you’re recommending. Since it’s a must-have that my URLs are “SEO and user-friendly” because they’ll be widely shared to generate inbound traffic, how can I do this URL swapping?

Maybe @petter, you could jump in and help us out with your expert knowledge?

Thx

I think it is crazy that they perform a secondary search if the actual object is already loaded after “document” loads. The whole concept of Slug was to make it a secondary unique identifier, and they even built in the auto append numerical sequencing based on existing ‘things’ with the same slug, so get ‘item’ ‘item-1’ ‘item-2’ if you were to attempt to add a slug of ‘item’ to the same data type when one or more already exist with that value.

Either way, I’m still wondering if @fede.bubble would be able to get us a technical explanation for why this occurs. Also as to why we get charged an extra 0.5 WU for a non logged in user creating/modifying data compared to a logged in user. There are just some mysteries that surround WU still; at least the technical rationale for some charges.

This will not work for your goals of human readable and shareable URLs, since it requires the user of the non-human readable use of a unique ID in the URL, which doesn’t look great, and was what slugs were introduced to fix for SEO purposes.

Is your app an SPA? When you have a blog page open are you maximizing on page SEO with other internal links to other similar articles (likely same category)…the reason I ask, is that if you are maximizing your SEO potential with other similar article links and/or have an SPA style app, my paid plugin Data Jedi would make the overall WU costs of loading the data less and improve the page load speed (if you are loading anymore than just one article at a time).

It also has an element called URL path List Extractor that allows you to extract up to five different path list items (perfect for any SEO focused app) using not just unique ID or slug, but ANY text field on any of the 4 types of data (custom data types, option sets, api objects, plugin objects) that Bubble supports natively. It has a nice separate (do not need the URL path List Extractor on same page) client side action to change the URL with a built in ability to remove/add in proper order (say goodbye the headache of conditional formatting which path list item belongs where or how to extract which path list item) - this is great for writing superb meta page titles and meta descriptions if you need that for a single page that can have various fields (like city, state, category, sub-category). The element also has built in, conditionally set, structured data for breadcrumbs and website (autodetecting).

The plugin also comes with elements for Structured data, inclusive of Blog and Blog List.

I know it doesn’t address the main issue of your concern, being charged a search when one is seemingly unnecessary, but it can definitely help with SEO overall.

yeah, the confusing part is that Bubble does include the blog_post in the initial document payload, but the client-side scripts still run a second lookup when the URL contains a slug. that extra search is tied to how Bubble validates the slug on the client before it commits the page thing. so even though the data is already there, the JS layer still fires that msearch and that’s where the extra WU + delay comes from.

about the URL swap: you don’t lose SEO at all as long as you do it after the page is already loaded. the idea is: load the page fast with the ID, render the content instantly, and then use “replace entry in browser history” to switch the URL to the slug without reloading the page. search engines see the final slug URL, users only ever share the slug, and you skip the extra search during load.

it’s basically what a lot of SPA frameworks do. you keep the friendly URL, but you avoid paying the performance penalty on the initial hit.

How does this work? If users share url with slug, the page is navigated to with slug in url, not the unique id. And how bubble functions, so long as a data type entry has a slug, if the user navigated with slug in shared URL it uses slug and can not override with unique id, and if shared with unique id and navigated to with unique id, bubble automatically replaces uid with slug since that data entry has a slug

@marpas @iamcharlesac @connect10 watch video below to understand behaviors of url path list, page content type, slugs and unique id

1 Like