Make your web app load faster all around the world



February 08, 2017
Castle works on a wide range of digital products: SaaS platforms, online communities and e-commerce / booking platforms. Often these products have international reach and need to offer good performance to users from all corners of the globe.

Making static websites load quickly is not a problem — all pages can be cached in a CDN and rendered from the nearest mirror — but for dynamic web apps which can't be cached efficiently this is a big challenge.

Improving dynamic web app performance may require dramatic changes to architecture (like switching to SPA architecture to minimize the amount of dynamic data transferred) or changes in infrastructure (like setting up separate servers for different regions).

Recently we've used a simpler approach which still results in visible performance improvements. That's Railgun™, a traffic compressor by Cloudflare, which speeds up data transfer from the origin servers to the CDN edge locations:
Without Railgun, Cloudflare works just like most other CDNs: it provides transparent caching proxies all around the world. Cacheable content is delivered from the nearest datacenter, but the dynamic content still has to be transmitted from the origin server(s) using standard TCP/IP and HTTP.
With Railgun, the dynamic content is transmitted between the origin server(s) and the datacenter via a permanent highly-compressed connection.
Image credits: Cloudflare, "Railgun™ Origin Network Optimizer"
Railgun uses the fact that from moment to moment there's usually a small change between versions of a page. According to experiments at CloudFlare, reddit.com changes by about 2.15% over five minutes and 3.16% over an hour. The New York Times home page changes by about 0.6% over five minutes and 3% over an hour.
Railgun looks for changes on a page from download to download, just like video compression looks for changes from frame to frame.
Benchmark, please!
Cloudflare claims that Railgun results in an average 200% additional performance increase. But I was wondering whether that's true for my particular app hosted at Heroku.

For the benchmark purpose, I created a simple Rails app with a single front page which resembles (from the data standpoint) many other Rails apps: it consists of 95% static content which doesn't change between requests, and 5% dynamic content like current time. I hosted it with Heroku:
Enabling Railgun for a Heroku app
First I configured my Heroku app with a custom domain delegated to Cloudflare (as explained in this guide), and turned on the "proxy" (CDN) mode:
Then I configured Railgun software. The regular instructions didn't work for me, because Railgun requires installation of specific software which listens on TCP port 2408. Heroku doesn't allow for listening on custom ports, so instead I used dockhero.io add-on to run Railgun in a Docker container alongside my Heroku app:
$ heroku addons:create dockhero
$ heroku plugins:install dockhero
$ heroku dh:generate railgun    # this generates dockhero-compose.yml
That last command created dockhero-compose.yml with the following content:
This configuration requires a valid RAILGUN_ACTIVATION_KEY, which can be obtained in CloudFlare Account Settings.
NOTE! Railgun is only available on Cloudflare's Business plan.
I assigned the activation key to a Heroku environment variable and launched the stack:
$ heroku config:set RAILGUN_ACTIVATION_KEY=xxx-put-your-key-here-xxx
$ heroku dh:compose up -d
Then I enabled Railgun for my domain and verified that it works by clicking Test button in Cloudflare:
The Experiment
To measure page loading speed from all over the world, I launched six Linux servers in different locations of Digital Ocean cloud provider, and performed some testing using Apache Benchmark CLI tool:
$ ab -t60 -c5 "https://railgun-playground.herokuapp.com/"  
$ ab -t60 -c5 "https://www.railgun-playground.tk/"  # tested twice: with/without Railgun
The origin server (Heroku app) is hosted in US East AWS datacenter, so access from New York is already very fast, and Railgun adds just a tiny performance boost. The effect becomes visible when the app is accessed from Europe, and especially from Asia, where Railgun speeds up data loading by 2-3 times.
Conclusion
Is it right technology choice for me? It depends on many factors, including the budget, data nature and end-users' expectations. In many cases Railgun can be a "just enough" drop-in approach, or at least a short-term performance fix.
Performance boost Setup complexity Monthly hosting expenses
Railgun 2x–3x Low $200–$500/mo
Maintaining servers in multiple zones 2x–30x* High (dev-ops effort) Cost of servers in additional zones
Converting to SPA 2x–30x* Very high (much coding) NO
*the performance boost for alternative methods is estimated based on the assumption that the page accessed from the nearest mirror in a "distant" region is loaded as fast as Heroku app from New York. The actual data loading performance boost depends on many factors, like rendering technology, data cacheability and local ISP bandwidth.