This is a post from Robin Sloan’s lab blog & notebook. You can visit the blog’s homepage, or learn more about me.

Cloud study

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

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

For my projects, that “some­where” has lately and reli­ably become cloud func­tions. They fit at least two ways:

Back in January, when I was putting this web­site together, I’d already imple­mented the sub­scriber tools on AWS Lambda when Google announced that their Cloud Func­tions would sup­port 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.

The winner

I appre­ciate 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 Func­tions, par­tic­u­larly in Ruby, par­tic­u­larly with the scaf­folding of the Func­tions Framework, has been a better expe­ri­ence in every respect.

There’s a simple, useful local devel­op­ment mode. The func­tion runs exactly as it would in the cloud, with no spe­cial setup or extra tin­kering required.

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

The single-page view of each func­tion is terrific. Google’s dash­board shows you every­thing you need to know in one screen: the func­tion’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 pro­vided the most potent dose of like, “suddenly expanded tech­nical capability” I’ve received since, I don’t know … Slicehost??

The mega function

One well-established draw­back of cloud func­tions is the “cold start” problem. When your func­tion is get­ting used a lot, the system spins up as many copies as needed; very slick. When it’s not get­ting used, the system spins up: zero. So, the first request after a period of slumber can be quite slow. One imag­ines the system ner­vously pat­ting its pockets: “Where did I put that code … ?”

It’s really not a huge deal, but there is a notice­able dif­fer­ence between the per­for­mance of a func­tion that’s “cold” vs. one that’s being pinged by a few thou­sand newsletter sub­scribers. The latter purrs; the former engages with a pal­pable ker-thunk.

The solu­tion I’ve chosen might be “bad” practice, but it works for me. Instead of deploying each of my func­tions as Actu­ally Dif­ferent cloud func­tions, I’ve rolled them up into one “mega func­tion”—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, per­forming a dif­ferent operation.

For routing, I use a para­meter in the pay­load 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 func­tion is that it “fails fast”; if some­thing isn’t working, nothing is working.

This is all in the con­text of an incon­se­quen­tial per­sonal web­site … but that’s not an uncommon con­text! Just because crit­ical enter­prise data­bases exist doesn’t mean we all need to pro­gram as if we’re sup­porting them.

Sloan’s mega func­tion: I rec­om­mend it.

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