Published April 11, 2023

Every month, I get an email from AWS charging me roughly $11. It’s for a side project, a container running on AWS App Runner that renders a gif with a simulation of Conway's Game of Life. The URL to invoke the container is then embedded in my Github profile. Why do I have a container running to simulate Conway’s Game of Life and render it as a gif for my Github profile? I dunno, I thought it was cool and unique idea that I didn’t see anyone else doing.

You might wonder, why not just render Game of Life in my GitHub profile? Why use this complex custom hosted setup? Well, you can’t run custom Javascript to customize your Github profile, that would probably lead to the next MySpace worm, but I thought it would be awesome if I could hack around that limitation and still make my profile dynamic.

But there are 3 problems with how I originally built this side project.

  1. It’s slow. Simulating a few hundred iterations of the game isn’t so bad, but rendering them to node-canvas, encoding every frame to a gif, and streaming that back to the client takes longer than one second. This means when you load my Github profile, there’s an awkward layout shift because the gif is loading in very late.
  2. This vanity project is costing me somewhere around $138 annually (because I have to keep the container constantly running to reduce cold start), and this is more than what I spend on my annual Spotify subscription, which actually provides value to my life in the form of crying to Taylor Swift after a breakup.
  3. It’s ugly! I’m spending all of this money and the gifs don’t even look good!!!!

Untitled

So, here’s how I fixed it.

First, I pre-generated the gifs. There is something cool about a truly unique simulation on every page load, but it doesn’t really matter. If you generate a sufficient amount of gifs and randomly distribute them, it’s good enough (a rare moment where product management school of thought wins over my engineer brain). By pre-generating the gifs, I don’t need a server constantly running. The simulation code I used is actually fairly straight forward.

Untitled

Rendering the cells is also fairly straight forward, as they’re just squares spaced evenly on a grid with a color picked from a gradient. The simulation and rendering code are both fairly isomorphic, as the only DOM API being used is the HTML canvas, which can be used in a Node environment with the npm canvas package.