---
title: "Optimizing the website's load performance"
author: Yarmo Mackenbach
slug: website-load-performance
date: "2020-06-05 22:47:21"
published: true
---

## My old webhosting

When I started making websites back in 2010-ish (maybe even earlier than that, I don't remember), I used shared hosting as I did not have the slightest clue about how a server worked, let alone set one up for web hosting. About two-three years ago, I switched to [Cloudways](https://www.cloudways.com/en/), allowing one to host websites on a virtual private server (VPS) and still not require any actual knowledge about the inner workings of a server.

## My new webhosting

However, I've been managing my own private server for almost two years so I felt confident I could do the hosting myself. Hip as I am (I am not), I decided to go with a [Caddy server](https://caddyserver.com/) as a [Docker container](https://www.docker.com/get-started) on a VPS hosted by [DigitalOcean](https://www.digitalocean.com/). For the low-traffic websites I currently maintain, this is largely sufficient.

I am in the process of moving each website one by one to the new hosting solution. It was time for this very website, [yarmo.eu](https://yarmo.eu) and I thought to myself:

> I should actually check if I gain any website load performance by moving to this new solution.

When asking the Fediverse, 70% predicted [Caddy would perform better than Cloudways](https://fosstodon.org/web/statuses/104285148110095796).

## Let's get testing

I decided to use [WebPageTest.org](https://www.webpagetest.org) to measure load perfomance. For each case described below, three measurements were performed and the median measurement is displayed and analyzed.

### Cloudways

First, a baseline measurement of my existing Cloudways solution.

![Cloudways - overview](/content/img/wpt_1_1a.png)  
*Cloudways - overview*

![Cloudways - rating](/content/img/wpt_1_1b.png)  
*Cloudways - rating*

![Cloudways - waterfall](/content/img/wpt_1_1c.png)  
*Cloudways - waterfall*

So the server returns the first byte of information after 480 milliseconds. Now, I should tell you that my website is based on [Phug](https://phug-lang.com), the PHP port of [pug.js templating](https://pugjs.org). The page is rendered in real-time and apparently, that takes a little over 300 ms.

It is worth noting that any other metric is then dependent on how the website is programmed. Once Cloudways has sent over the data, it no longer has any influence on load performance.

The website if fully loaded  after 923 ms. Good to know. About a second to wait for my website to load.

Over on the waterfall, we see a bunch of files being downloaded simultaneously after the HTML page is loaded. The largest asset to load is the profile picture.

Wait, what is that `F` over on the rating? Security is NOT in order! As it turns out, Cloudways does not handle security-related HTTP headers for you&hellip; I did not know that! They [recommend setting these headers in a .htaccess file](https://support.cloudways.com/enable-hsts-policy/).

Let this be a reminder to all of you: test your websites. One might learn a few tricks.

Anyway, can Caddy do better?

### Caddy

![Caddy - overview](/content/img/wpt_1_2a.png)  
*Caddy - overview*

![Caddy - rating](/content/img/wpt_1_2b.png)  
*Caddy - rating*

![Caddy - waterfall](/content/img/wpt_1_2c.png)  
*Caddy - waterfall*

Well, as it turns out, it's largely the same performance. First byte arrived after 459 ms, but I've ran it a few times and there's really little difference between Cloudways and Caddy.

BUT! Learning from my previous mistakes, I configured Caddy to set up all the correct headers and won't you look at that, `A+` on the security score!

So that's it then?

Well, not really&hellip; I learned that my website wasn't running optimally because I forgot some basic HTTP headers. Did I forget more? In other words, can I do even better than this?

I've tried a lot of things, I'll just narrow it down to the two most important findings.

### Caddy - inline most of it

As it turned out, I had a few small SVG icons and some CSS files. I tried rendering them into the HTML page, so the data would be sent on the first data transmission and no separate requests were needed. For good measure, I also minified the CSS files which, for one file, reduced the size by 30%!

![Caddy+inline - overview](/content/img/wpt_1_6a.png)  
*Caddy+inline - overview*

![Caddy+inline - rating](/content/img/wpt_1_6b.png)  
*Caddy+inline - rating*

![Caddy+inline - waterfall](/content/img/wpt_1_6c.png)  
*Caddy+inline - waterfall*

On the waterfall above, you can clearly see the `dank-mono.css` was not inlined but I tried multiple configurations, there was no real gain as the image also needed to load and took longer anyway. So, all in all, inlining the SVG and CSS content did little in this case.

Also, note the regression from `A+` to `A` on the security score. There was one header I couldn't quite get working properly so I had to disable that one, other than that, it's working better than it ever has.

What drew my attention for the final step was the `B`. My server responds in within 480 ms and that it still not good enough for you, WebPageTest? Ok, have it your way.

What takes my server so long to respond? Well, obviously, it must be the templating. Can I improve the template? Perhaps. But as it turns out, I don't have to! Ever heard of caching?

As described on [their website](https://phug-lang.com/#usage), PHUG has support for caching and even calling an optimized version of their renderer. So I applied both caching and optimized rendering.

### Caddy - PHUG optimization

![Caddy+PHUG - overview](/content/img/wpt_1_7a.png)  
*Caddy+PHUG - overview*

![Caddy+PHUG - rating](/content/img/wpt_1_7b.png)  
*Caddy+PHUG - rating*

![Caddy+PHUG - waterfall](/content/img/wpt_1_7c.png)  
*Caddy+PHUG - waterfall*

Well, there it is!!! First byte of data arrived after a mere 173 ms, website is useable in less than half a second and all scores are `A`!

That's the result I was hoping for. Now on my todo list:

- Optimize the profile picture further or try SVG
- Get all HTTP headers perfect

Any comments or recommendations/optimization? Please [let me know](/contact)!

<!-- https://www.webpagetest.org/result/200604_Z3_05019c9c3f872873bd1e964474cb0dac/ -->
<!-- https://www.webpagetest.org/result/200604_E2_026978bdd64ce5830ecf5be74b634120/ -->
<!-- https://www.webpagetest.org/result/200605_M4_b728be8e608e4807af0192cefaf55f2e/ -->
<!-- https://www.webpagetest.org/result/200605_CF_96d815e43897af2723f7a4d762d76ba3/ -->
<!-- https://www.webpagetest.org/result/200605_61_67b241dc40cbaf08ed257177e6efbef0/ -->
