top | item 12774277

Building a Shop with Sub-Second Page Loads: Lessons Learned

271 points| DivineTraube | 9 years ago |medium.com

96 comments

order
[+] diafygi|9 years ago|reply
I work in energy, and there's a saying: "The cheapest kwh is one you don't use."

Want to make your website faster? Don't send so much stuff. Removing unnecessary code or content from your site has always had the biggest impact on performance. Unfortunately, it seems that often the people in charge of increasing performance aren't the people who get to choose what has to be on the website.

The Website Obesity Crisis: https://vimeo.com/147806338

    I want to share with you my simple two-step secret to improving the performance of any website.
    
    1. Make sure that the most important elements of the page download and render first.
    
    2. Stop.
[+] blaze33|9 years ago|reply
100% this, there is a nice presentation about the bloated web but I couldn't find it now. Remember that performance is a feature: https://blog.codinghorror.com/performance-is-a-feature/

That being said having a fast loading site and being able to serve a spike in load are two different issues (even if having fast loading pages in the first place obviously helps).

Also don't forget that measuring (page size/response times/etc.) is the the first step. You can't optimize what you don't know!

[+] sotojuan|9 years ago|reply
Here's an easy way to do it:

Want to make your website faster? Use a 3G connection when developing or testing. Chrome Dev Tools make this easy and you can also adjust the latency as needed.

[+] ehnto|9 years ago|reply
The UberEats homepage is 30mb of crisp imagery and fonts. I understand their target market is people on retina screens sitting on the hefty piped intranet of their trendy startup, but 30mb is a complete egress from sensibilities.

There isn't even that much content on the page, it barely goes past the fold.

[+] cyberferret|9 years ago|reply
I concur. I did some cursory research the other day, and I noticed that most websites I visit (blogs, shopping sites etc.) now have total asset download sizes that are several times BIGGER than major enterprise software applications that I used to install on my PC 20 years ago. This is just for 'front end' stuff for the browser experience.
[+] draw_down|9 years ago|reply
This reminds me of the joke where it's like "how to draw a face" or whatever, where step 1 is draw the outline, and step two is do the rest.

In other words, the devil is in the details of how to accomplish #1. It is pithy though, I'll give you that.

[+] z3t4|9 years ago|reply
Always let the content have the highest priority when designing a web page.
[+] kilroy123|9 years ago|reply
Great work. When I loaded the page I even thought to myself, oh shit this is fast.

One huge problem, with most large platforms for e-commerce stores, they are terrible at speed optimization!

For example, I have a store on Shopify and it's basically impossible to do most of what you explained. With Shopify, you can customize HTML / SCSS files with dynamic content. All of which gets compiled on their back-end. You have no access to the final compiled HTML and markup. You're sadly limited in what you can do.

It seems you need to have a custom store to really be able to optimize this hard-core.

[+] hbrundage|9 years ago|reply
This is largely incorrect. All the front end customizations that this article describes are possible with Shopify because you have complete control over the HTML, JS, and CSS that the platform spits out. While true that you can't "access" the final compiled HTML to edit it, the templates that power your theme are very close to that output, and not hard to change if you're familiar with HTML/CSS. The Javascript optimizations are all completely possible as well but you either have to pick a theme that has been optimized or implement them yourself in your own theme. Shopify also supports AMP and responsive themes (because it's just HTML).

It is true that with Shopify or similar platforms you aren't able to make backend choices or implement caching like the article has described, and yes it's true that all the themes in the theme store aren't perfectly optimized for page load time -- but the question really is do you want to do any of this stuff yourself? Shopify has invested years in their platform to make your website as fast as possible for as little money as possible. The themes that Shopify publishes in the theme store undergo huge amounts of performance testing to ensure that you aren't losing money from latency. The platform comprises a world class CDN, and Shopify doesn't charge for bytes through it. The platform uses many layers of backend caching at the data access, logic, and rendering layers to make your shop as responsive as possible if anyone has been to it before. Shopify powers some of the biggest sales on the internet that truly dwarf Good Morning America. The platform is also geographically redundant such that an entire datacenter can fail with only a moment of visible impact to you and your customers. If what I'm saying is true and you don't actually sacrifice that much flexibility on the Shopify platform, why would you choose to have to implement all the above?

Another angle is operations: How many people do you think they have monitoring it and ready to respond to any incidents? Shopify serves an order of magnitude more traffic than Baquend saw at the very peak of this occurrence every single minute of the day with a better response time on average.

The Shopify platform took an army of engineers 10 years to build so it would seem unlikely that Baquend has all the same features and stability. How much do you think Baquend charged Thinks to build this? Is it more than $29 / month?

Source: work at Shopify and built many of these systems.

[+] merb|9 years ago|reply
they could do even better. I mean something is really bad here, since their uncached css from frankfurt to my house should not take over 100ms. and they also serve images, css and js from the same domain. and they download the text's as a extra request. and somehow http2 doesn't kick in.
[+] crdb|9 years ago|reply
I checked out Baqend ("we" in the article) and the site prevents me from navigating back when I press "back" (I think by injecting itself as the previous page - I'm not really up to date on dark patterns).

This is the kind of behaviour that is an auto-no for me when buying B2B, not just by itself but because of what it signals about the company. I recommend you remove it.

On the article itself: you can do very fast pages off a relational DB. In one case, the round trip on a Postgres full text search for auto complete on millions of rows from multiple tables was so fast we had to add a 10ms delay - on a $5/month VM.

[+] DivineTraube|9 years ago|reply
We fixed that problem and deployed it. It turned out to be the iframe with the tutorial app. That sets a new hash with a random todo list id and that captures the back button. It was not intended to keep people on our site.

Thanks for pointing the issue out!

BTW, I agree, RDBMSs are a great choice if the hot data set fits in main memory and queries are well-optimized through appropriate indexes. Issues usually only start to occur if 1) the data set is too large 2) queries cannot be optimized by the query optimizer and involve full-table scans 3) interleaved transactions contend on few rows.

[+] daveguy|9 years ago|reply
It looks like the dark pattern they used to get that "no back" behavior is: "open in a new tab".

Edit: I stand corrected, link from the article opens in a new tab, so the back issue is moot there. Definitely red flag behavior. Baqend folks, if you are listening, you should fix it, and if it is the default behavior of your framework you should definitely fix it. No one likes hijacked back buttons.

[+] dahdum|9 years ago|reply
Great info on how to optimize.

However, in basket, I clicked "Zur Kasse" to checkout, and the response took 11.08 seconds to get to the checkout page per Chrome network tab. Repeated multiple times with same result.

Also, I don't see any product detail pages, categories, search result pages, or anything other than 7 products on the homepage that add directly to cart. Does this strategy scale to regular ecommerce site levels?

[+] DivineTraube|9 years ago|reply
You're pointing out an important point: third-party services have to be fast, too. The call that starts the checkout does a synchronous request to Paypal Plus, which has very ugly request latencies from time to time.

The shop is indeed quite minimal at this time. The optimizations scale very well to regular ecommerce sites, though. Detail pages and categories can be cached very well, as they only change by actions of human editors. A notable exception are recommendations. If they are item-based (e.g. a-priori algorithm) they can also be cached very well. If they are user-based (e.g. collaborative filtering) that part has to be fetched from the server-side recommendation model. The same is true for search results. The heavy-hitters, i.e. the most-searched-for keywords are cached, while the others are fetched from the database. That is the part where server-side scalability and latency optimization is of utmost importance. At Baqend we support both MongoDB full text indexes and automatic separate indexing in an ElasticSearch cluster with automatic CDN and browser caching for the most frequent search results.

[+] cpcallen|9 years ago|reply
I am amazed that it is 2016 and people talk about sub-second page loading times as if it is an accomplishment to be proud of.

That it is an accomplishment of a sort (in contrast to the depressing reality of bloated websites everywhere) shows just how badly wrong we have gone.

Maybe we should force web devs to go back to dialup; then we'd get sites that have the performance of http://info.cern.ch/hypertext/WWW/TheProject.html again.

[+] inian|9 years ago|reply
We also realised that tackling web performance takes a lot of effort..so have been building different tools which can automate front end optimization techniques. Our recent tool (https://dexecure.com) tackles image optimization by generating different formats (WebP, JPEG XR), different sizes of images and compressed to different qualities depending on the device and browser the user is using. All of the images are served with a fast HTTP/2 connection.

We have seen people integrate with it in under 5 minutes and cut down their page size by 40%!

[+] rkwz|9 years ago|reply
+1 Images are a great starting point for improving page load performance as they sometimes represent a big chunk of the total page weight.
[+] sotojuan|9 years ago|reply
Very good view to an often ignored part of web development.

And as usual, the Medium posts loads way slower than the actual website.

[+] user5994461|9 years ago|reply
> Furthermore, browser caching is highly effective and should always be used. It fits in all three optimization categories because cached resources do not have to be loaded from the server in the first place.

That is incorrect.

The browser issues requests for all cachable content with a last-modified-date [or similar special metadata], the webserver replies with a 304-not-modified + empty body, if the file was not updated.

There are still HTTP requests sent, there is still network latency, there is still server processing involved. [Worst case scenario: For tiny JS/css/icon files, the latency might dominate everything and nullify the benefits of caching].

It gets more complex: Since a few years ago, Firefox stopped issuing HTTP requests ENTIRELY for some cached content. It speeds the load time but it causes caching issues.

Last I checked, chrome and IE didn't adopt this behavior yet. That may or may not chance in the (near?) future.

P.S. I felt like being pedantic about caching tonight. Otherwise, a nice article =)

[+] DivineTraube|9 years ago|reply
You're right that browser caching has a few tricky parts, which is why we do a some things differently.

What you describe is an HTTP revalidation (If-None-Match, If-Modified-Since) which the browser triggers in two cases:

-if the TTL defined in the Cache Control header has expired

-or if the user hits F5

In the normal case where a user revisits a site, the browser takes all the cached resources without doing a revalidation and that is the case one should optimize for.

The cases you seemed to have in mind is explicit refreshes (F5), expired cache entries, or servers that respond with a max-age=0 header (which is useful in many situations).

The most difficult part when caching dynamic data is purging stale content from browser caches. Because if the TTL is too high and the content changes ealier, users will see stale cached data. At Baqend we solve this problem by piggybacking a Bloom filter of potentially stale URLs to the client [1]. The client checks the Bloom filter to determine whether to do a revalidation or use the cache. In order for the Bloom filter to remain small, we have a learning TTL Estimator that calculates TTLs by approximating the expected time to the next write.

[1] https://medium.baqend.com/announcing-availability-of-baqends...

[+] nimrody|9 years ago|reply
> There are still requests sent, there is still network latency. [In the case of small JS/css/icon files, the latency can be as much as the transfer time].

What? When the "Expires" header indicates the item is still valid the browser should use the cached object without making any requests.

Some servers (Rails for example) just serve assets with "Expires" set to some distant future time. When they want to expire these files, they simply change the name (hence the long numeric suffix appended to js/css/etc. files)

[+] paulddraper|9 years ago|reply
304, not 204.

There have been proposals for "immutable" or similar additions to Cache-Control that would not have the validation.

[+] WhitneyLand|9 years ago|reply
Great article Erik et al. Shows how engineering requires grounding in theory, clever implementation, and lots of trial and error.

Is there a particular target customer space that you are focused on?

[+] DivineTraube|9 years ago|reply
We built Baqend around the caching algorithms that we developed at the university. Our goal was to make the performance optimizations applicable to as many contexts a possible. We went for the "serverless" pardigm and backend-as-a-service to accelerate any application (website or app) that uses our APIs and hosting.

Currently most of our customers are e-commerce, web and app agencies, startups and software companies that look for web performance in combination with scalability.

We're currently getting lots of request from e-commerce, so we are building out our support for shop features (e.g. advanced search, payment, content management). We are developing a Magento plugin to make the transition to our platform and its performance benefits as easy as possible.

[+] ecommerceguy|9 years ago|reply
FWIW there are some clever Magento shops running pretty stout at sub second load times on AWS. Puts Magento back in the upper echelon for carts again, imo.
[+] thekonqueror|9 years ago|reply
Can you please share some URLs of faster Magento stores?

I'm working on a similar project that will offer optimization as a service for e-commerce. I'm curious to see what others are doing.

[+] CurlyBraces|9 years ago|reply
This must be really frustrating when your startup gets so much attention that your shop breaks down and you end up making no money out of that
[+] chetanahuja|9 years ago|reply
Oh the irony. The Medium page this blogpost was hosted on is ~3.5MB in size and took ~5 seconds (on my 20Mbps cable internet connection with 11ms ping to cloudfront) to first readable render.
[+] CydeWeys|9 years ago|reply
It's interesting to me that the website "thinks.com" is entirely in German. I'm used to seeing sites on .com in English, and indeed I can't even think of another site right now that isn't.

Why didn't you use the .de ccTLD? Given that most German websites are not using .com domains, isn't this potentially confusing, and causing you to lose traffic? You don't even own thinks.de; it's blank.

[+] haylem|9 years ago|reply
You're mistaken. A lot of businesses in many countries use .com addresses even for their local shops.

For one othing, .com stands for "commercial". .us is for USA.

Regarding whether it's right to do so or not is another question. For starters, it depends on the regulations of each country, as in some of them you simply are not allowed to operate under a different TLD. But most countries are not this restrictive.

One of the many things that were supposed to "make sense" at the dawn of the web, and that were quickly abused and evolved into more than what anyone could possibly have thought of at first. (No, no, I'm not thinking of HTTP at all while writing this. Why would I?)

[+] icebraining|9 years ago|reply
I'm used to seeing sites on .com in English, and indeed I can't even think of another site right now that isn't.

If you mostly frequent English sites, that's not surprising, but in reality many .com sites are not in English. Some reasons include restrictive ccTLD rules (for example, until 2012 you couldn't register a .pt domain, only .com.pt/.org.pt/etc), better recognition of the TLD by users and SEO.

Some examples from the top 200 sites: http://baidu.com, http://qq.com, http://taobao.com, http://sohu.com, http://naver.com, http://coccoc.com, http://globo.com

[+] markdown|9 years ago|reply
.com domains are usually cheaper and usually much easier to register than ccTLD's.

In my country, the ccTLD costs more than double the .com equivalent, and requires manual intervention to set up. I have to wait for a guy (and it's just one guy who's been handling it for over a decade) to show up for work on Monday, go through his emails, finish his coffee, and then manually set up my DNS.

Given the above, .com's are always the first choice.

[+] meta_AU|9 years ago|reply
5ms average load latency. But the max looked like it was more than 5 seconds.
[+] DivineTraube|9 years ago|reply
The JMeter load tests were conducted to test the throughput of the CDN and backend setup (browser caching was disabled). The load generating servers where hosted in Frankfurt (Germany) where the CDN (Fastly) also has an edge location. This lead to average response time of 5ms. We experienced some hickups within JMeter causing single requests to stall up to 5 seconds. For the 10 million requests we got an 99.9th percentile of below 10ms. We couldn't quite figure out why JMeter had these hiccups, maybe those were GC pauses, maybe something else, but it was consistent across different setups and servers.
[+] imaginenore|9 years ago|reply
I get pretty bad layout thrashing upon load.
[+] meira|9 years ago|reply
I Look at it only to criticise but it is really fast, congrats.
[+] nucotano|9 years ago|reply
I feel concerned by this new trend of using slow languages/stacks and the "we'll fix it later" mantra. I can't believe there are webpages such as reddit with such horribly awful generation times, do their tech guys sleep well at night?
[+] conorh|9 years ago|reply
This is not a new trend. This is a trend since the dawn of, well, as long as I've been programming, ~20 years now. Turns out that most of the time there are many more important things than your stack or language speed, and yes, often times "fix it later" is the right tradeoff.
[+] arbuge|9 years ago|reply
I'm surprised you would mention Reddit in this context. It seems to me they're one of the lightest websites out there, which is not really surprising seeing they're mostly serving text. Reddit and HN are pretty much the only two websites which are useable on my Raspberry Pi 2s.
[+] gooeyblob|9 years ago|reply
What would you do if you were in charge of engineering at reddit?