My latest project —, a content site with near-zero costs and near-100% PageSpeed: Part 1

Timothy Teoh
5 min readJan 23, 2021


When some friends approached me recently to build a new site, I thought it would be a good chance to try out some development techniques that I had been itching to validate. After working off and on over the past couple months and in overdrive over the new year holidays, was released and it’s a site I’m really proud of!

Two things I wanted to focus on were:

  1. Creating the cheapest, but most scalable, site possible.
  2. Creating the most performant site possible.

Part 1: Pay-as-you go Wordpress with headless mode and static site generation

If you’re like me, you remember the days before VMs and containers. Wordpress sites were something you hosted on a shared server, and if your traffic grew, you would have conversations with your hosting provider, usually ending up on one (or many) dedicated server(s).

Even after VMs and containers and even CDN offloading have become mainstream, the monthly fixed costs of a high-traffic Wordpress (or any other CMS) site can easily run into thousands! There is a popular headless mode now for Wordpress, which treats it like an API which you can build modern frontends on — but even that has its limitations.

The database is the hardest/most expensive to scale; and the autoscaling VMs/containers aren’t free either.

The database Wordpress depends on is the hardest thing to scale, and not coincidentally, typically the most expensive component. The diagram above shows a fairly standard setup — as I mentioned, more modern techniques may use the headless mode to put in a more advanced database or ways of serving content, but you typically end up with the same paradigm: Autoscaled VMs/containers fronting a database. On a highly trafficked site you probably want redundancy on the data layer as well, increasing costs even further. A CDN can alleviate this, but if your site is popular enough, you need to have your architecture cater for an invalidation event that will still send traffic to the underlying database.

If you’re really like me, however, you remember the days even BEFORE Wordpress, at the start of the World Wide Web. Back then, we manually uploaded static HTML files and images into Geocities for every page we needed — no fiddling around with databases or scripting!

While the term “serverless” gets bandied around a lot today, it usually only means you don’t manage the underlying servers (they are still there). And if you rely on a database, that’s not really “serverless”. Serving content from static files, meanwhile, actually does mean there are no servers (or databases) to worry about.

Static site generation is the key here — a newer approach that is becoming popular because of just how cost-efficient it is and how well it suits the use-case of a content site, because many content sites update relatively infrequently, compared to say, a social media platform.

Separating your content authoring from your publishing and content serving

You really have two things you typically want to do with most CMSes:

  1. You have a small team of writers who update the CMS.
  2. You want to serve the content as efficiently as possible.

And these concerns are separate.

Only writers need to access Wordpress; the world only needs the static files that get generated.

Going cheap on Wordpress content authoring

I ended up using the cheapest VM I could find (a $3.50/mo Lightsail instance) to host Wordpress in. Since only writers needed to access this, I didn’t need a dedicated database, or even redundancy (I snapshot this though).

Content publishing with on-demand resources using GatsbyJS

The critical middleman component here is GatsbyJS, the most popular static page framework. Built on React and GraphQL, it generates static pages from content (with plugins for major CMSes like Wordpress and Contentful). The framework will be immediately familiar for anyone who works with React and GraphQL:

  • Wordpress posts, tags, categories etc are queries using an easy WPGraphQL schema which frees you from having to work with the underlying database.
  • GatsbyJS has familiar React tools like UI frameworks (I used Chakra-UI), thumbnail generation using Sharp, and Webpack. The only thing to remember is that you aren’t building any sort of SPA, and all pages and thumbnails get generated during the build process — it is a lot like developing an entirely server-side rendered app, just that everything gets pre-rendered.

Three gotchas though:

  • The big gotcha is that because you are not serving content from Wordpress itself, you will need to ensure any plugins you install are compatible with the underlying WPGraphQL layer — to be honest, this can be a good thing, as having too many plugins tends to cause security and performance problems. In my case, I had to carefully curate to a set of plugins that fit what we wanted to do, but that were still compatible with WPGraphQL: Advanced Custom Fields and PolyLang for multilingual support.
  • The GatsbyJS build takes a couple minutes to run. This is typically not an issue (get a coffee or something).
  • Because Wordpress is only being used as a CMS, previews may not reflect the actual site. You can work around this by not having GatsbyJS be on-demand, as it has a development mode that can preview changes, or modifying the Wordpress theme to roughly approximate the Gatsby site.

The result for was a build process that is only triggered on-demand, when content is updated. That means I didn’t need to run VMs 24/7 — the GatsbyJS build only needs to run when there is updated content, and upload the resulting files into S3 (or any cloud storage of choice). I used Netlify to host the GatsbyJS build, as they have a free tier that only charges you for build minutes (Update: I’ve since migrated the build into Google Cloud Build, to save even more on build-minute cost)

Infinitely scalable content serving with S3 and Cloudfront

The last bit will probably be familiar with most developers: Put a CDN like Cloudfront in “front” of your static files on S3, and make sure the CDN gets invalidated when new content is published.

The result is a site that:

  1. Is infinitely scalable and will never go down, since there is no database involved.
  2. Costs only as much as the traffic it serves and the amount of content published.
  3. Is 100% secure, which is important given that Wordpress is the most hacked CMS in the world due to its ubiquity. Whether you’re in-house or a freelancer, it gets very difficult to keep up with updates for Wordpress sites.

That’s it for creating the cheapest, but most scalable, site possible - comments welcome! Read part 2 for the other half of the project: making the site as performant as possible.



Timothy Teoh

Full-stack software architect and technology leader from Kuala Lumpur, Malaysia