Skip to content
Deep Dive

Hybrid Glide caching in Statamic

Since 6.34, Statamic can cache Glide images in a third way. Pages render without waiting for their images, and once an image exists, the web server delivers it without PHP. Getting there took two rounds of review and a follow-up fix in 6.35.

· 5 min read · Thomas Sausen

Two modes, two trade-offs

Glide creates image variants on request. A template asks for a width or a preset, and Glide resizes the original. Until September, Statamic offered two ways to handle the results, set with the cache option in config/statamic/assets.php.

With caching off, which is the default, pages render quickly, but every image request goes through PHP, even when Glide has already generated that image. With caching on, Glide writes the files to the public folder and the web server delivers them directly. The catch is that every variant gets generated while the page renders.

Marty Friedel described the problem in an idea for Statamic with a concrete example. A page with ten images, each in five JPEG and five WebP sizes plus a fallback, means 110 images to generate before the page can load. On a busy site, the first mode means many PHP processes for every page view. The second can block a page or run into time and memory limits.

How hybrid works

Duncan McClean's pull request, released in 6.34 on September 22, adds a third value:

'image_manipulation' => [
    'route' => 'img',
    'cache' => 'hybrid',
    'cache_path' => public_path('img'),
],

In hybrid mode, the Glide tag writes the URL where the finished image will live, but doesn't generate it. When a browser first requests that URL, the file doesn't exist yet, so the request reaches PHP. Statamic generates the image, saves it in the public folder, and returns it. Every later request finds the file, and the web server delivers it without PHP. It's the same idea as full static caching for pages, applied to images.

For this to work, the cache path has to be the route's folder inside public, so public/img for the img route. If the two don't match, the web server never finds the files, and every request keeps going through PHP. Statamic logs a warning once when that happens. The default server configurations for Nginx, Apache, and IIS need no extra rewrite rules.

What the review found

The idea is simple, but it rests on one promise: the URL Statamic writes into the page must point exactly to the file the generator creates later. Jason Varga's review spent most of its time on that promise.

In the first round, he set the pull request back to draft because of a security issue. The fix was to register only the hybrid route in this mode and drop the older /asset and /http image routes. That closed a way to make the server generate images in bulk, since only URLs that Statamic wrote during rendering can now trigger a new image.

The second round found a subtler bug. For watermarks, video thumbnails, sites with a URL prefix, and file names with characters like #, the predicted path and the written file didn't match. The image still loaded, because PHP answered every request, so nothing looked broken. But the file never ended up where the web server looked for it, and hybrid quietly behaved like caching off. Jason suggested testing the promise itself rather than each case. Duncan added a test that requests each URL and checks that the file exists exactly where the URL points, running it against a table of inputs from local assets to remote URLs.

Before you switch

Switching from cache: false changes every image URL, so old links to /img/asset/… and /img/http/… return 404. Switching from cache: true keeps the URLs. The hybrid cache always lives on the local public disk, so custom filesystem disks aren't supported in this mode.

Statamic keeps the link between each URL and its source image in the Glide cache store. Behind a load balancer, that store has to be shared between servers. And after php please glide:clear, statically cached pages have to be rendered again, because their image URLs no longer resolve.

The same problem showed up in an ordinary editing step. In #15512, GitHub user florianbouvot reported that reuploading an asset deleted its generated images and those links but left statically cached pages in place, whose image URLs then returned 404. Replacing an original from the crop editor is such a reupload. Static caching listened for saved and deleted assets, but not for reuploaded ones. Statamic 6.35, released on October 1, clears the affected pages on reupload.

A related report is still open. In #15432, changing an asset's focal point with cache: true removes its generated images, and statically cached pages keep pointing at the old files unless something else clears them. If you combine static caching with either cached mode, check that your invalidation rules cover your asset containers.

Is it worth switching?

For sites that already use cache: true, hybrid is the easiest win. URLs stay the same, and pages no longer wait for every image variant before rendering. For sites on the default, the gain depends on traffic and image count. A small site with a few images per page won't notice much. An image-heavy site with real traffic saves a PHP request for every image view after the first one, which adds up quickly.

Before switching, make sure the site runs 6.35 or later, so reuploads don't break cached pages. If it runs on several servers, share the Glide cache store between them. And if it uses static caching, check the invalidation rules for your asset containers. With that in place, hybrid combines the fast pages of the default mode with the fast images of the cached one.

Sources

Author

Thomas Sausen is a freelance web developer and the editor of Flatbard. He builds with Statamic and writes about the surrounding ecosystem.