Going Static, Quickly
June 27, 2016
I've always enjoyed tinkering with this diminutive site, and lately I've continued the quest to improve speed and uptime while staying ruthlessly cheap about it. The result has been a switch from Statamic to a static site generator called Sculpin, along with a hesitant return to CloudFlare. It took about a month of experiments and minor breakthroughts to get there.
I quietly got around to supporting SSL for my site in late February, mostly to be a good citizen of the internet. A recent series of Webfaction outages got me thinking about ways to circumvent downtime, and I was inspired by a client's deft use of Fastly to solve the problem. I wandered my way into some requirements for this latest endeavor:
- Generate a static site to eliminate the need for any application caching.
- Use a CDN for whole-site caching and global mirroring in the name speed and relative immunity from downtime, with an edge node in Seattle because I adore low pings yet will not relocate for them. (With an idealistic global page load time of <1s, and initial connects in <10ms.)
- Switch entirely to SSL (https) URLs so PRISM has to try a little harder.
- Keep using a bare domain without any www because it looks nice that way.
Here's how that went.
Generating the site with Sculpin
I've been happily using Statamic since 2012, and it dawned on me that I don't have any compelling reason for a CMS since I'm the sole author of a tiny, infrequently-updated site. Statamic has a static generator built in, but I figured I'd go all the way and remove the CMS from the equation. Jekyll seemed like the obvious choice, but Sculpin was a bit friendlier thanks to its reliance on Twig templates and native post tag handling.
The only roadblocks were easy to clear: I built a simple PHP form handler (hosted on a subdomain) and went through some dark URL rewriting to convince Apache to do without trailing slashes.
It also turns out that a rather critical aspect of being cacheable is asking to be cached. I've not always taken the time to specify cache headers, which can be a crucial mistake if a cache service is handling requests at face value. Like CloudFlare, for example, which tends not to cache HTML responses unless specifically asked to, rendering the Always Online™ feature worthless if it's got no cached page to serve.
I used my .htaccess Apache directive to set Expires and Cache-Control values for different file types, and whipped up a shell script to publish the Sculpin site, copy .htaccess into the mix (which Sculpin otherwise leaves out), and publish it to Webfaction via
Choosing a CDN
This long journey had me comparing KeyCDN, Fastly, CloudFront, MaxCDN, CacheFly, section.io, and poking at CloudFlare again.
I could have used KeyCDN for full site caching, and it would have been really fast and really cheap with free custom SSL. Pings and TTFB to KeyCDN's nodes were easily <10ms for most of my tests, and I would have lived with having to serve the site from a secret domain to have it pulled into a zone and served at workingconcept.com. (Pulling from workingconcept.com while serving from it created an infinite loop. Derp.) KeyCDN even offers origin shielding, which is another impressive offering from one of the least expensive CDNs around. A seemingly impatient support response confirmed what I suspected: there'd be no good way to serve the site from a bare domain. The bare domain is also called an apex domain by those with better vocabularies, and it would turn out to be the greatest challenge among my list of requirements. While I could use DNS Made Easy's proprietary ANAME, which is kind of a CNAME living on the root A record, doing that robbed KeyCDN of its ability to distribute traffic geographically and instead served every request from its Washington D.C. node. I thought about going
www and couldn't. I contemplated living without global mirrors, and couldn't.
So on I went to Fastly, which is a shockingly fast service built on Varnish. A client uses it for its web product, which helped me appreciate Varnish (which is like a software memory stick) and Fastly's platform. My site would be on Fastly now if I wasn't priced out of it for this humble blog. While I could have skated by for free with my low traffic, full SSL and whole-site caching would have been prohibitively expensive. This was confirmed by an uncommonly personable and hilarious support agent.
I've been using Amazon CloudFront for static assets since early 2014, and while it could have been a viable option I didn't want to switch to Route 53 for DNS since it never seems to appear in the top tier of performance benchmarks. I generally find AWS to be a bit more slow and a bit more expensive than alternatives, even though it's a vast wonderland of integrated services.
MaxCDN had a nice control panel, impressive speed, and a handful of nice options like the ability to designate an IP address—rather than a domain name—for a pull zone. As I learned with KeyCDN, this can make it easy to pull from the origin you're also shielding. The lovely admin interface was littered with upsells, and an agonizing cancellation process ultimately confirmed that whole-site caching wasn't going to be possible with a bottom-tier (cheap!) client.
CacheFly's control panel was an uncomfortable journey back in time, and I promptly fled once I figured out that whole-site caching—or anything more than hosting static files—wasn't going to be a good idea there.
section.io was intriguing and confusing enough that I toured it twice. It's sort of like a scrappy Fastly, made up of various pieces that developers and ops folks would mostly likely appreciate. Where Fastly had a well-unified, seemingly polished control panel, section.io's often left me uncomfortable and uncertain what I was getting into, even though it was clearly a flexible product aimed at fitting in with developers' workflows. Like Fastly, it made it possible to combine Varnish with a CDN. Custom SSL would have been free, and I might have easily afforded low apex domain traffic by handing over DNS to section.io. Support was prompt, personal, and friendly, and engineers fixed an innocent DNS issue that I had as I was kicking the tires. Unlike Fastly, inexperience with Varnish may have kept me from being qualified to work with section.io. A confusing inability to cache static pages and lackluster CDN speeds led me reluctantly away.
And that's how I returned to CloudFlare. I've been routinely scared away from free accounts over infuriating 522 errors, with CloudFlare blaming an unresponsive server while the server's usually perfectly happy and healthy. I've had better luck with paid CloudFlare accounts using full DNS setups (as opposed to CNAME only), and Railgun is really nice when it's an option. My tests with CloudFlare yielded heartening waterfall timings with <100ms total for a simple static page, all over the globe—from that all-important apex domain. While custom SSL wasn't a cheap/free option, I don't mind the shared certificate1. I also don't like CloudFlare's messaging during an outage because I'd prefer that a visitor not even know the origin went offline, but at least all this thrilling content can weather a storm.
DNS Made Easy has been consistently fast and issue-free since I started using its DNS service in February 2014. But I bravely and/or foolishly left a good thing and pointed my DNS to CloudFlare.
I'm back on CloudFlare, finally specifying appropriate cache headers, with a completely static site served via https on a bare (apex) domain. The plan has so far succeeded, and I'm curious what my uptime will look like in the coming months.