It goes without saying that we use Rails a lot here at 37signals. Often times, when we look at a problem, we turn to Rails or something similar, because when you have a high-performance precision screwdriver, everything starts to look like a finely engineered screw. Sometimes, what you really need is a big hammer, because what you’re looking at is a nail.
Our public sites – sites like 37signals.com and basecamphq.com – are a perfect example of this.
Let me tell you about our journey with these sites over the years, and how we’ve landed on a simple solution that boosted conversion rate by about 5%.
Good enough
There’s nothing particularly dynamic about these sites; we might throw a “Happy Monday” in there, or we might make some tweaks based on a URL parameter, and we A/B test them extensively, but there’s no database or background services involved.
Stretching back to the pre-Basecamp days, the 37signals.com site was written with PHP. There was no Rails back then, Ruby wasn’t commonly used for web development, and DHH and others worked in PHP, so it was the logical choice. As we added sites, they continued to use PHP since it was fast and easy. This worked well for years and years—our public sites were relatively performant and rock-stable, and we didn’t really have many problems. The biggest pain was in setting up for local development, which ended up being quite the pain to get set up in OS X in a way that behaved well with Pow, Passenger, etc.
Getting better
A few years ago, Sam Stephenson and Josh Peek wrote Brochure as a way to translate our marketing sites to Rack apps. This solved the local development challenges, and let us use a language we were all generally more comfortable with. It was a little slower than PHP, and meant dealing with Passenger on deployment, but it was a fair compromise at the time. We moved one site to brochure, and then ran out of steam to move the rest – work on our applications took a higher priority.
A few months ago I took a serious look at our public sites’ performance. They were making a lot of requests for individual assets and page load times were pretty poor – Basecamp itself loaded much faster than the essentially static signup page for it. Local setup problems with the PHP sites also meant that it was harder to work on the sites, and so we were less productive and less inclined to work on them.
Back to the basics for fun and profit
Our solution to this (in addition to spriting images and cleaning up unused styles and Javascript) was to switch to using totally static HTML pages. We’re using the stasis gem to compile .html.erb
files locally and on deploy, along with Sprockets to pre-process and concatenate stylesheets and Javascript. Our web server ends up serving plain old HTML and a single CSS and Javascript file, with no interpretation.
This makes local development easy, and what you see locally is always what will be deployed. This also makes it trivial to distribute the marketing site to multiple datacenters or distribution networks around the world—just upload the compiled files, rather than worrying about dependencies for running an interpreted site.
While we haven’t done that yet, just from some mild spriting and cleanup and moving to static HTML, we shaved about half a second off the total load time for basecamphq.com, and saw about a 5% improvement in conversion rate result from that (the link between page speed and conversion rate has been studied more rigorously as well by the likes of Google, Amazon, etc.).
Sachin
on 08 Feb 12Noah great post. The 0.5 seconds you shaved off -was that in end user load time or server side processing? I realize it would have the same impact nevertheless to the end user – but curious to know. Also how do you measure this load time – any specific tools?
Thanks Sachin
Mattias
on 08 Feb 12As I always say: You can write crappy code in every language.
Lee
on 08 Feb 12Might be able to shave even more time off by using a CDN for your non-HTML assets.
erferf
on 08 Feb 12rer
Cormac
on 08 Feb 12You’re reporting time saved in absolute units and the change in conversions in relative units. Makes it hard to tell whether the observed difference is meaningful
Tomislav
on 08 Feb 12That result is perfectly aligned with Amazon’s research – 100ms speedup = 1% better conversion rate.
Gregory Schnese
on 08 Feb 12“we shaved about half a second off the total load time for basecamphq.com, and saw about a 5% improvement in conversion rate result from that”
Did you A/B test the slower version of the page vs the fast one? What if people who came to the signup page were more likely to signup in general? (They might have come via positive press.)
I’m sure a faster page is better for signups, but it’s not clear that you can claim a 5% boost from my understanding of this post.
Wolf
on 08 Feb 12Correlation does not imply causation, it’s january, I can imagine a lot of business try to start the first of the year for bookkeeping reasons, so numbers might just be up because of that. Or some other reason. You never know. But a speedy website is a good thing anyway.
Nikolay Petrov
on 08 Feb 12Yes, just keep the good work coming. Every site must target to meet 100 in PageSpeed/YSlow ranks. It is not that hard and is the basic that could be done. Even without changes in the code at all.
ecomware
on 08 Feb 12Schlossnagle, standing on the shoulders of giants, wrote about the benefit of processing content into a static form in his book on scalable architectures back in 2004. It has been something of a crusade to convince and encourage development managers and their senior developers not to chase every crazy fad that comes along and detracts from the core properties of network systems while optimizing for convenient workflows or client-side latency. (How is it possible that whole books were written on image sprites, but so few chapters on eliminating page-processing for essentially static pages?)
Good post. Keep up the good work.
Jeff Putz
on 08 Feb 12“Performant” is still a noun, not an adjective. Only developers make up silly words like this. Even if it were an adjective, it doesn’t tell you if it means “high” or “low” performance.
Scott
on 08 Feb 12I will sign-up if you will shave another 0.5 seconds.
Yeah, right.
Milan
on 08 Feb 12Speed is one of the things I like to praise 37signals for, however it is good to see they did not stop working in that area.
I am sure going static worked well for you but maybe you should rething that strategy for http://status.37signals.com/ – constant refreshes make it impossible to read the page and interruptions get annoying as does the constantly refreshing window and spinning icon. There must be a better way how to do this.
Benjamin Lupton
on 08 Feb 12Could not agree more. This is the direction we’ve taken with DocPad – https://github.com/bevry/docpad/ – you write your website as files, and if they are static files, it’ll generate a static output file, if they are dynamic files, it’ll re-render them on each request. In the soon to be released v3 it’s even got support for ruby, erb and php, along with the usual eco, jade, markdown, stylus, sass, less, coffeescript whatever support you’d expect from a language agnostic system. Well worth checking out.
Glenn Plas
on 08 Feb 12Perhaps you should dump Apache and use nginx instead since you are all static now…. That would be another 5% convertion on Basecamphq.
Anonymous Coward
on 08 Feb 12Actually also marketing people use it, business people, advertisers as well, etc. Making up words is how the language got from “uga uga” to Shakespeare (not to mention how many words Shakespeare himself first used).
It is common understanding that it means high performance.
Matthew Bloch
on 09 Feb 12Heh, we’ve been running a very similar solution (even down to the obvious project name, template & URL layout) for years on bytemark.co.uk and bigv.io. I used Sinatra, and that’s sortof my default framework. I did some fancy stuff around it to build page indexes, automatic redirects from old pages, it runs Thin on MRI for everything including static assets but we have varnish sat ahead of it, so only one visitor every five minutes sees Ruby actually serve a page.
Silumesii Maboshe
on 09 Feb 12Very useful post. What informed your choice to use statis over other tools like jekyll, nanoc etc?
Rudolf Olah
on 09 Feb 12How are you serving those generated static html pages? Half a second improvement doesn’t seem like enough because doesn’t load time also depend on how many requests can be handled by the web server? I know that apache can serve static html very quickly and handle hundreds of requests vs. something like a PHP website that uses a framework…
Anonymous Coward
on 09 Feb 12I prefer middleman, but stasis looks good too.
Also, use nginx instead of apache. With the memcache module.
William Mengers
on 09 Feb 12Noah,
Excellent post, I’ve been thinking for a whole now that it just makes sense to work with a more simple set of files when no framework or bloats cms is needed. Recently at work, we used Drupal for a one page landing site and while I gave my 2 cents much like yours above, we still went with a full blown framework. That’s amazing you were able to shave off a half second and the improvement it had on your conversion rates. Just another reason to keep page speed in check. Thanks again for sharing.
William Mengers
This discussion is closed.