Discourse performance

Jeff Atwood, co-founder of Stack Overflow and Discourse, wrote:

We’ve always put a heavy emphasis on performance at Stack Overflow and Stack Exchange. Not just because we’re performance wonks (guilty!), but because we think speed is a competitive advantage. There’s plenty of experimental data proving that the slower your website loads and displays, the less people will use it.

While it matters for regular webpages, community sites lose momentum when pages load slowly. I make it a habit to periodically auditing my sites’ responsiveness. PageSpeed Insights is a pretty good test of page speed. Here’s what the metrics of my blog look like on mobile:[1]

Screenshot 2024-04-01 at 1.20.25 PM

My blog is pretty much an ideal case after I fixed some obvious problems. It’s a simple static site with optimized images. When I say static, I mean it only really gets updated when I:

When I don’t do those things[2] the site doesn’t change.[3] In contrast, an active community on Discourse will have a site that changes frequently. Unfortunately, dynamic sites don’t fare as well in the metrics. Meta Discourse likely represents the best case for Discourse sites:

Screenshot 2024-04-01 at 1.46.12 PM

Discourse gets a big demerit in performance from the 3.3s First Contentful Paint (FCP) metric. Quoting from PageSpeed:

First Contentful Paint marks the time at which the first text or image is painted. Learn more about the First Contentful Paint metric.

In contrast, my static blog comes out at 2.4s FCP, which is about a second faster. Both sites load a lot quicker than that on my internet connection, but the test is showing what might be more typical for visitors. In any case, a faster site helps increase traffic from search engines and return visitors.

Why some sites are slow to load

Imagine a website like a piece of IKEA furniture. Instead of being delivered fully-assembled, your web browser assembles each page from pieces delivered from the site’s servers. In the early days of the web, a page consisted of an HTML file and maybe a few images. A modern webpage might include dozens, if not hundreds, of other files:

  • Cascading Style Sheets (CSS)
  • Javascript
  • Icons and emojis
  • Fonts
  • Etc.

You know how every IKEA product comes with a little hex key wrench? It seems like a waste to get another wrench each time you buy an new shelf or whatnot. Well, websites have the equivalent of hex key wrenches, which is to say, files that are used by many sites. Instead of getting a new copy with each page, the browser reuses the same copy of common files over and over. These saved files are said to be “cached” and it’s an important method of speeding up all sorts of computer processes including sending information around the world.

Caching allows web browsers to reuse anything. It’s as if you could get one screw from IKEA and reuse it for every product you buy from them in the future. As long as pages use the same version of a file, the browser can reuse it without having to do the equivalent of going to the store to get the parts. If you’ve ever lost a critical part in a DIY project, you know how costly it can be to have to make a run to the store for replacement parts and the modern internet avoids round-trip time (RTT) whenever possible.

Stranger yet, you can start using websites before they are quite done being built. It’s as if you built a chair from IKEA and someone started using it before you add the finishing touches. If you pay attention to complicated sites, such as Facebook and LinkedIn, you’ll see parts of the page pop in as the page loads. This is why First Contentful Paint is significant. Since people usually read a page from top to bottom, it really doesn’t matter how long it takes for the bottom of the page to render. Practically speaking, getting the main parts of a site delivered as quickly as possible really matters.

This is where a static site can have a huge advantage. Every time a site’s content changes, the server needs to send updated copies of some of the files that make up a page. If the page hasn’t been updated, there’s nothing new to send and various caches can speed up the page.

Not all static sites are fast

One of my clients has a static site that doesn’t do particularly well on the PageSpeed test:

Screenshot 2024-04-01 at 5.55.38 PM

For now, let’s ignore the SEO score. This indicates how likely search engines[4] will show the page at or near the top of search results. Instead, look at the Performance score, which is quite low. The first problem is that it take 5.0s for the Largest Contentful Paint (LCP):

My static blog weighs in at 2.9s LCP. Why the difference? My client’s site has two very large images that must be downloaded from the internet. Not only does that take time, the images also cover up a large portion of the screen which blocks visitor from reading the text on the page until they are loaded.

This causes another problem: Cumulative Layout Shift (CLS):

Cumulative Layout Shift measures the movement of visible elements within the viewport. Learn more about the Cumulative Layout Shift metric.

You might not know the acronym CLS, but you have experienced it when you visit a page that seems to load in fine and suddenly moves around on the screen. It’s especially annoying when you are about to make a selection and the page shifts so you make a choice you didn’t intend. This happens when the browser starts to render the page and then the site inserts an instruction that changes the layout. My client’s site has some code that resizes the large images, which is a really common cause of CLS.

This should never, ever happen in a static site because the designer arrange the order to avoid shifting content at all. To use the IKEA analogy, it’s the difference between assembling a chair starting with the legs and seat (so someone could start sitting in it right away) and adding the legs late (so you have to ask the person to move after they already sat down). At the very least, a static site should save space for images to indicate there’s something missing.

Discourse fixes performance right out of the box

I had a theory that Discourse would work better at serving a static site than my client’s existing static site. So I took the page, copied the text, uploaded the image to one of my test Discourse instances and got this result:

Screenshot 2024-04-08 at 11.59.02 AM

The image was still too large, but the layout didn’t shift at all. I wouldn’t exactly call this as good as a static site, but it’s substantially better. Discourse also improved the SEO metric (98 compared to 88) without any special tweaking on my part. Discourse automatically sets up the page to perform very well on the PageSpeed Insights tests.

Getting the most out of Discourse

That was good, but I’m not done yet. How can we reduce the impact of large images without manually resizing them? Thankfully this is a problem that was solved years ago via Content Delivery Networks (CDN).

To go back to the IKEA analogy, imagine if the only way to get a replacement part was to travel to IKEA’s headquarters in Leiden, Netherlands.[5] Thanks to the speed of light, single sources of data isn’t as inefficient as single sources of furniture parts. CDNs do exactly what IKEA does: set up distribution centers around the world with copies of the parts consumers might need. In particular, I used Cloudflare, a popular CDN, to cache my test site. The result is stunning:

Screenshot 2024-04-08 at 11.55.55 AM

This is very nearly as good as my static blog with a Discourse site. Using the same content as the slow static page but hosted on Discourse behind Cloudflare, this example page passed all the performance tests with flying colors:[6]

Not every site, nor even every page on a site, will get these results. My client has a page with an embedded Google map that blocks the page from rendering. Moving that code to my test Discourse instance doesn’t help at all.[7] You can’t always control the content that gets posted on an active community, so perfection should not be the goal.

I’m shifting to Discourse + Cloudflare when possible

Setting up Discourse with Cloudflare was a little tricky. I broke my test sites several times before I hit upon a working configuration. Knowing that my visitors get the best possible experience makes it all worth it in the end.

If you’d like help getting the most of Discourse, contact me or put a meeting on my calendar.

  1. The rest of this post will look at mobile stats in order to compare like to like and because mobile performance is particularly important these days. ↩︎

  2. And I’m not for the moment. ↩︎

  3. Outside of the occasional comment. ↩︎

  4. Specifically Google, which is the biggest source of most page’s traffic. ↩︎

  5. I assumed it was in Sweden, but they moved for tax reasons. IKEA has a complicated corporate structure that seems designed to avoid taxes. ↩︎

  6. Which is to say, “green”. ↩︎

  7. The solution is to use Google Maps Static API. ↩︎

A quick note: moving to Cloudflare meant I need to jump through some hoops to connect to my servers via SSH. It’s enough of a pain that I’ve moved this site off of Cloudflare for now. We’ll see how it goes in the future.