Robin Sloan
the lab
March 2021

Cloud study

A lovely impressionistic watercolor of an anonymous patch of clouds.
Cloud study, anonymous, 19th century

The website you’re reading is mostly static HTML, just web pages on a CDN, but for newsletter subscribers, it does offer a few bits of interactivity, and those bits require code to run somewhere other than your browser.

For my projects, that “somewhere” has lately and reliably become cloud functions. They fit at least two ways:

Back in January, when I was putting this website together, I’d already imple­mented the subscriber tools on AWS Lambda when Google announced that their Cloud Functions would support Ruby. I did a little inves­ti­ga­tion and was so impressed that I switched every­thing over; now, I want to share a couple of findings.

This message was emailed to lab newsletter subscribers. The assumed audience is subscribers who maintain their own websites or other small apps. (Here’s more about assumed audiences.)

The winner

I appreciate AWS Lambda’s role in kick­starting the whole “floating wisp of code” model, but/and I have found the system itself very funky to work with. Google’s Cloud Functions, particularly in Ruby, partic­u­larly with the scaf­folding of the Functions Framework, has been a better expe­ri­ence in every respect.

There’s a simple, useful local devel­op­ment mode. The function runs exactly as it would in the cloud, with no special setup or extra tinkering required.

Dependencies are as easy as a Gemfile. AWS, by contrast, requires funky “layers” that you need to build and maintain separately.

The single-page view of each function is terrific. Google’s dashboard shows you every­thing you need to know in one screen: the function’s activity over time, how quickly it’s responding, how many copies are running, etc. It’s perfect.

All in all, Google’s system has provided the most potent dose of like, “suddenly expanded technical capability” I’ve received since, I don’t know … Slicehost??

The mega function

One well-established drawback of cloud functions is the “cold start” problem. When your function is getting used a lot, the system spins up as many copies as needed; very slick. When it’s not getting used, the system spins up: zero. So, the first request after a period of slumber can be quite slow. One imagines the system nervously patting its pockets: “Where did I put that code … ?”

It’s really not a huge deal, but there is a notice­able differ­ence between the perfor­mance of a function that’s “cold” vs. one that’s being pinged by a few thousand newsletter subscribers. The latter purrs; the former engages with a palpable ker-thunk.

The solution I’ve chosen might be “bad” practice, but it works for me. Instead of deploying each of my functions as Actually Different cloud functions, I’ve rolled them up into one “mega function”—really almost a tiny app.

The result is that when someone arrives to, say, modify their newsletter subscription, they rouse the code not only for future subscription-modifiers but for anyone who might need any part of it. That might include their future self, performing a different operation.

For routing, I use a parameter in the payload called method:

case body["method"]
when "get_tags"
  Society.get_subscriber_tags(body)
when "update_tags"
  Society.update_subscriber_tags(body)
when "send_response"
  Society.send_response(body)
when "check_email"
  Society.check_email_status(body)
end

Another advantage, for me, of putting every­thing into one mega function is that it “fails fast”; if something isn’t working, nothing is working.

This is all in the context of an incon­se­quen­tial personal website … but that’s not an uncommon context! Just because critical enter­prise databases exist doesn’t mean we all need to program as if we’re supporting them.

Sloan’s mega function: I recommend it.

Pretty much the same as the first watercolor, but with the red glow of sunset.
Cloud study, anonymous, 19th century

March 2021, Oakland