A lot of my sites, including this one, had been running happily for years on Webfaction - it was relatively inexpensive and developer-friendly, allowing SSH access and support for a number of languages, including Python. Unfortunately, a year or so ago, Webfaction was aquired by Godaddy. Godaddy has a pretty poor reputation (to put it mildly) - including stories that their CEO went on a safari to shoot elephants - so I decided to move all my sites away from Webfaction.

Most of my other sites are static and are React-based, so shifting those was easy enough. The original version of this site, though, used Django as the backend, which allowed me to create posts through a web admin section. It also required a database to save posts, and I was running Memcached in front of the server to help speed up the site and reduce database access. This seemed like a lot of work to set up again, so I wanted to see if there was another option which would hopefully be a lot quicker for me to set up.

Converting to static

The only part of my site which was really dynamic (ie requiring database access) was the blog - everything else, like the projects on this site, were pretty much just templates pulling in the relevant static files. If the blog posts were static, then the entire site would be static and I could use a static site generator.

I’ve been using Gatsby at work so decided to give that a go; the only drawback to moving my site over was having to copy all of the blog posts out of the database and into Markdown files. While it was a bit of a chore, it was pretty straightforward since HTML is also accepted in Markdown: the only real changes I needed to make was adding frontmatter to each post to make sure the metadata turned up.

Once all of the posts were ported, then the layout and styles were very simple to move into Gatsby: the template layouts just needed converting into JSX, and the styles could be dropped in as-is.

Once the site was built, deployment was a doddle: I used CircleCI to set up a build and test stage, and once successful the static files were deployed to my server.

Comparing stacks

So far, I’d call the move a huge success: the new site is far simpler in terms of creating posts and maintenance, and is much cheaper to run.

Previous stack (Webfaction/Django)

  • Python 3
  • Django
  • Postgres
  • Memcache
  • Apache (Django app)
  • Nginx (static files)

Cost: £12/month

New stack (Digital Ocean/Gatsby)

  • Nginx

Cost: £5/month (along with several other of my sites)

The above does gloss over the build process a bit, which is running on a free CircleCI plan. However, the new stack is so much simpler to set up and maintain - I didn’t have to worry about setting up a database, or migration or backups for it, or set up a memory cache to serve dynamic pages, or having a separate server to handle static files and so on. The added bonus is that since my site is now just JS and HTML, it runs perfectly happily on a £5-a-month Digital Ocean droplet. An extra added bonus is that I don’t share the droplet with other people’s sites, so setting up Let’s Encrypt is easy - Webfaction servers were shared and had a shared server in front of everything, so SSL certificates were a bit of a pain to set up.

So overall, Gatsby is really impressive and works well for my site.

And now, Rust

And now, what you’ve all been waiting for: Rust! This was a good opportunity to see how Rust would fare for an existing site with a decent amount of traffic. I have a little team generator web app which has around nine thousand impressions a week; the old version on Webfaction was running on Flask, and for the rewrite I decided to use Actix. This is probably (massive) overkill, since it just needs to respond to one route, but I’m fairly familiar with Actix from other projects so went with what I knew.

Results of rewriting in Rust

To be honest, this section is boring: it was fine. The logic is simple enough, everything’s small enough to fit into a single source file, and building and deployment is all handled by CircleCI. On the server, the app is run by supervisor and sits behind the same Nginx server as the rest of the site.

I don’t have any stats comparing the previous version with the new version since I forgot to measure the performance on the old version and DigitalOcean’s graphs aren’t working at the mo, but it seems quick enough and I’m nowhere near the droplet’s memory limit, so chalk this up to another great Rust success story!

One gotcha I had with Actix is that GET doesn’t seem to respond to HEAD requests, which Flask and Node servers both do, which meant pings from a monitoring to the app always failed until I manually added HEAD statuses.

So there we go, moving hosts and completely changed the stack was fairly straightforward!