Skip to content
PEWES ENERGY

Engineering

Fifteen pages in under a day

9 min readPEWES ENERGY

The PEWES pewee and wordmark from the Grape Madness wrap

This site went live and Google had fifteen of its pages in the index in under twenty hours. That is not a record and it is not magic. It is what happens when the things a crawler needs are all present at once, and it is a reasonable proxy for the whole argument about why a storefront like this costs what it costs.

Speed and discoverability are usually sold as two line items. They are one system, and this is what it is made of.

The page that arrives before it is asked for

A conventional WooCommerce page is assembled when you request it. The server loads the framework, then the plugins, then the theme, runs a few dozen queries and prints the HTML. A few hundred milliseconds, repeated for every visitor, on a good host.

Here the page already exists. It was rendered once, cached as HTML, and the only thing that moves per visitor is the part that genuinely differs: the cart count, the stock line, whatever belongs to you. A crawler asking for a product page gets a complete document, immediately, with the text and the prices already in it. There is no second request it has to make to see the content, and no script it has to execute to find out what the page says.

That matters more than it used to. A crawler that has to render JavaScript to see your product description will get there eventually. A crawler that is handed the description in the first response gets there now.

Caching on two levels, and why that is the hard part

Anything is fast when nothing changes. Staying fast while an editor edits a price, a warehouse changes stock and an author publishes an article is the actual engineering.

There are two caches in front of this site and they invalidate together.

The application cache holds rendered data, and every entry is tagged with the facts inside it rather than with the page that served it. A cached catalogue response carries the taxonomy terms it contains. So adding a drink to one collection clears the responses that mention that collection and leaves the rest alone. The alternative, which is what most sites do, is to clear everything on every change and rebuild the whole catalogue because somebody fixed a typo.

The edge cache sits in front of that, in Cloudflare, so a visitor in Frankfurt is served from Frankfurt. The problem with an edge cache is that it does not know what a product is. It knows URLs.

So WordPress tells it. Every time something is saved, a plugin sends one batched message describing what changed: which product, which slug, which taxonomy terms, whether it was published or deleted or restocked. The storefront turns that description into the exact list of addresses affected. A stock change on one drink clears that drink’s page, the page of its range, the shop index, the home page and the product feeds. Six or eight addresses. Nothing else in the cache is touched.

Before that list is purged, the storefront quietly rebuilds each of those pages itself, so the first visitor after the purge is served a finished page rather than waiting for one to be built. The order matters: purge first and you hand the next visitor a slow page, and the cache stores that slow moment for everybody behind them.

What the crawler was actually handed

Fifteen pages in a day is not one trick. It is the absence of every common obstacle at the same time.

  • A sitemap with sixty one addresses, generated from the live content rather than maintained by hand, so a page that exists is in it and a page that does not is not.
  • Titles and descriptions written by a person. The SEO plugin still owns those fields in WordPress; the storefront renders whatever it is told. Nothing is generated from a template and left.
  • Structured data that matches the page. Products carry price, availability, brand and reviews as data, not as a decoration bolted on by a plugin that guessed.
  • Canonical addresses that are stable. One address per product, one per range, no session parameters, no duplicate paths for the same thing.
  • Images in modern formats at the size the layout asks for, converted on demand, rather than at whatever size somebody uploaded.
  • No render blocking. The page is readable before any of the interactive parts have loaded.

Any single one of those is unremarkable. Having all of them on launch day is what compresses weeks into hours.

The scores, and what they cost

This site scores in the nineties on mobile and full marks on desktop in Google’s own page speed test, on a home page that carries a real three dimensional can, lit and rotating.

That combination is not free and it is instructive. The three dimensional scene is loaded only after the page is interactive, and only on hardware that can actually run it. The testing environment Google uses has no graphics card, so it falls back to software rendering and burns seconds of processor time on a scene nobody can see. The storefront checks what it is running on and skips the scene entirely when the answer is software, which means the code for it is never even downloaded there.

That is a small example of a general rule. Fast sites are not fast because somebody enabled a cache. They are fast because of a hundred decisions like that one, each of which required somebody to measure rather than assume.

The surfaces that are not browsers

Search engines are no longer the only thing reading a shop.

The same catalogue that renders the shop also produces a Google Shopping feed of a hundred and fourteen items, generated from the live data, so a price change on the site is a price change in the feed rather than a spreadsheet somebody re-uploads on Fridays.

It also produces a plain text description of the site for language models, a machine readable catalogue, and a documented API. When an assistant is asked to compare energy drinks, the thing that decides whether this shop is in the answer is whether its data was legible at the moment the question was asked. That is a build time decision, and it is cheap to make at the start and expensive to retrofit.

Where the speed actually comes from

It is worth being precise, because the claim gets made loosely.

It is not the framework. A badly built site on a fast framework is a slow site.

It is that rendering was removed from the request path, that the cache knows what each entry contains so it can throw away the right things, that images are generated rather than uploaded, and that everything expensive on the page is loaded after the page is usable and only where it will work.

Those four properties have to be designed in. None of them can be added by a plugin afterwards, which is the reason this is a build rather than an optimisation pass.

What this is worth to a business

Speed is a conversion rate and discoverability is a customer acquisition cost, and both of them compound.

A shop that is indexed in a day instead of a month starts earning a month earlier. A product page that loads before the visitor decides to leave converts a visitor who would otherwise have been a bounce. A catalogue that is legible to search engines, to shopping feeds and to AI assistants is present in three places where competitors are present in one.

That is the argument, and it is the only part of this article that is not a technical detail. The engineering above exists to produce those three sentences.

Measured, not assumed

The hardest discipline in performance work is refusing to trust a plausible story.

During this build a single function was blamed for eight seconds of processor time in a page speed report. The reasoning was sound, the function was expensive looking, and it was rewritten. Then it was actually timed: forty five milliseconds. The real cause was somewhere else entirely, and the only way to find it was to rebuild the exact environment the test runs in.

That environment turned out to be the answer. Google’s test runs a browser with no graphics hardware, so the three dimensional scene on the home page was falling back to software rendering and burning seconds on a picture nobody would ever see. The fix was to detect that case and skip the scene entirely, so the code for it is never even downloaded there. Mobile went from the sixties to the nineties.

The general rule is worth more than the specific fix. A performance problem that is explained rather than measured is a guess, and guesses cost a day and fix nothing. Anybody selling you performance work should be able to tell you what they measured, with what, and what the number was before and after.

The content delivery network is where fast sites break

There is a configuration that looks like the obvious right answer and is a trap, and it is worth describing because a version of it exists on a large number of sites.

A content delivery network can be told to cache a file for a year and to ignore whatever the origin says about caching. For files whose names contain a content hash that seems perfectly safe, because a changed file gets a new name.

It is safe right up until the origin returns something other than the file. During a deployment window a request for a script can be answered with an error page. The network is under instruction to ignore what the origin says, so it stores that error page under the script’s address for a year. Every browser afterwards receives an error page where a script should be, and nothing on the site works. It is not a slow site at that point, it is a broken one, and it stays broken until somebody purges the whole cache.

The correct setting is to respect what the origin sends. Hashed files already carry a year of caching in their own headers, so nothing is lost, and an error response carries instructions not to cache it, which is exactly the behaviour you want.

The lesson generalises: a cache that is told to ignore the truth will eventually store a lie, and the stronger the cache, the longer the lie lasts.

What to ask for in a report

Page speed scores are a starting point and they are easy to game. Three questions are better.

  • What does the page weigh on a phone, and how much of that is executed before it is readable? A score can be high while a page is still shipping a megabyte of script that nobody needed.
  • What happens when the catalogue is ten times larger? Speed that depends on having forty products is not an architecture.
  • What happens after an editor changes something? This is the one that separates a site that was fast on launch day from one that stays fast. If the answer is that the whole cache is cleared, the site will be slow every time somebody fixes a typo.

This shop is a working demonstration of what a headless WooCommerce build is capable of, and everything described here is running on it. If you are weighing a build of your own, it was made by Pavels Web Solutions.

Back to the journal

Keep reading.

Engineering8 min read

Paying for customers, not for signups

Every customer here has a referral code, and the reward arrives when the person they sent places their first paid order. The timing is the whole design, and the rest is about fraud.

Read the note

Engineering9 min read

A loyalty scheme with no points

No points, no wallet, no balance. Spend is measured two ways at once and the kinder answer wins, and twice a year a real voucher appears with your name on it. Here is why, and what it takes to make it correct.

Read the note

Engineering8 min read

A booking system is a scheduling system

The reseller call booking on this site is, almost exactly, what a consultancy sells and what a hotel sells. Here is what is underneath it, and what actually changes when you charge for the slot.

Read the note