This weekend, I finally deployed a new project I've been working on! It was a surprisingly difficult journey.

The new project is a game that's architected much like Manygolf. It has a Node WebSocket server, that I use to store game state in memory and send messages between clients. It also has a client-side application that isn't rendered or delivered by this WebSocket server - it's just some static files.

## Investigating Options

So, for the first time since I started using my DO VPS to host things two years ago, I started looking into other services for backend hosting. And, dang, the web changed a lot in the interim!

### Zeit's Now

So, my first thought was, “this is a pretty small game, I should look into some of these new quirky services that have popped up for managing microservices.”

now (as it's stylized on the site) is one such service. I was really excited about it, because it seemed perfect for my use case - just a simple Node app.

Unfortunately, Now has a bunch of issues. First off, the pricing is, well, hilarious. They have two plans, “open source” (free) and “premium.”

The open source plan always exposes your application's source at a special /_src URL. This is super weird, but, sure, my game is going to be open source anyways. It also doesn't allow custom domains, and Now generates a new domain every time you deploy. So now I can deploy my game to an ever-shifting-URL; god only knows what kind of weird process I'd have to put into place to properly route to it. Oh, and you only get twenty free deploys a month. It usually takes me about that many deploys just to get something running remotely without errors, so, uh, this plan is no-go.

### Heroku

My next thought was to look at Heroku. I'd used Heroku back in early 2013 for some side projects and liked it a lot - at that time, it was by far the easiest way to throw a Python or Node app online.

They've changed their pricing since then, but I was happy to see their pricing seems relatively in-budget for a side project. Heroku has this neat concept of “dynos,” which are basically just processes. Every Heroku account gets a shared pool of 1000 free dyno-hours a month, and each free app is allowed 1 “web” dyno and 1 “worker” dyno.

The math works out reasonably well if you, like me, are running a single process: a single app running for 30 days uses 720 of these dyno-hours. However, here's what's really nice - Heroku actually puts free web dynos to “sleep” after a half hour of inactivity. The Heroku docs are super unclear on what the hell “sleep” actually means (I think it basically means “terminated?”). Anyways, I was fine with my app losing its in-memory state while inactive, and fine with the initial connection to it taking 5-10 seconds as it comes out of sleep.

Pricing becomes potentially rough once you get out of this free tier, though. Heroku plans are priced in terms of “number of dynos per month.” The “hobby” plan is $7 per dyno/month, which at first seemed way too expensive to me. Turns out, though, that these dynos are prorated to long they actually run during a month. So if you have, say, a single web dyno, and then a worker dyno that runs once a day for one minute, you'd only get billed for 30 minutes out of that month's pricing. If you want, you can also pay$stupid amounts of money for simple horizontal scaling and more RAM. I think these plans only exist for people who have far more money than time (so, basically, startups who locked themselves into using Heroku for the time being). If my game ever got successful enough to need these plans, I would probably be figuring out how to monetize it, so I might actually be able to stomach the pricing.

Anyways, beyond just hosting processes, Heroku also has a ton of extra services you can add on. The two I care about are Postgres, which you can host for free for up to 10k rows, or for $9/month for up to 10 million rows. “Per-row” pricing is conceptually really stupid, and I wish there was like a$3/month tier where you get a million rows or something, but these both seem fine to me for getting started.

They also have free Redis hosting, which is potentially interesting. Thing is, the main use case I have for Redis is for helping scale my games. For example, if I'm finding I have too many players on my server and can't handle the messaging throughput, I could horizontally scale the game by adding more server instances and moving game state into a Redis database shared between them. If this happened, though, because of the per-dyno pricing I mentioned earlier, I probably would have to move the game off Heroku - I wouldn't be able to afford to scale horizontally.

Lastly, I've got one beef with Heroku that goes beyond pricing: somehow, after nearly a decade of existence, they still don't have a static hosting platform. If you want to host a static site, you have to either set up a Node/Python/whatever server to serve it, or you have to go through another service, like S3. Never understood why a service that tries to manage so much of your hosting in one place doesn't incorporate this obvious feature.

### surge.sh

Finally, I took a look at one service I actually had used before, Surge.

Surge is awesome. It's a static site host that has the interface I wish my DigitalOcean box had. You tell it a folder and a desired subdomain, and it'll deploy it there, for free, with HTTPS. It's amazing. Surge is the only service on this list I love enough that I'd throw a swag sticker on my laptop to give it free marketing.

Of course, Surge is a static site host, so it doesn't really solve my backend problem. But it did give me a thought - could I just put my static frontend on Surge, and then host my backend on some other service?

## My New Setup

It turns out, yes, I could. My new game is hosted on Surge and Heroku, and it took about 30 minutes to deploy.

The one quirk, of course, of having your frontend and backend hosted by totally separate services is that you usually need a bit of CORS configuration. I say usually because, hey, guess what web protocol doesn't use the same-origin policy for some reason? WebSockets! Yes, what's usually an obnoxious security flaw actually became an advantage for once.

I'm hosting my app for free across Surge and Heroku, and the deploy process is just:

# deploy the backend
git push heroku master
# build the frontend
npm run build
# deploy the frontend
surge --domain mygame.surge.sh --project build/


It's pretty awesome. And Surge actually supports custom domains for free, so if I decide I don't like that unsightly surge.sh domain, I can grab whatever the cheapest Namecheap TLD is at the moment and use that instead.

If Surge ever folds because they offer a ludicrous amount of features for free (or, more likely, they get acquired by a less-charitable company), then moving shouldn't be too hard - short-term, I could SFTP my static frontend onto my DigitalOcean box and just host the frontend on that. There's a bit more lock-in on the Heroku side, especially if I start using them for Postgres/Redis, but the backend code itself didn't change at all for Heroku, so it's theoretically still pretty portable.

The other exciting part of this is that it should scale for as many new games as I want to make. Surge gives you infinite projects for free, and with Heroku's free dyno hours system, as long as none of my games suddenly become consistently popular, I can put as many backends as I want on there for free.

I've had fun running my little DigitalOcean box, but I feel happy about using this stack for the foreseeable future. With deployment solved for now, it's going to be much easier for me to get ideas up and running as fast as I can come up with them, instead of spending time bogged down in server configuration and management.