Adam Argyle

Bye Deno, Hello Cloudflare

Read the original on nerdy.dev โ†—

So Deno, I still really align with it. I had a blast customizing the crap out of an artisanally rolled server rendered blog I built on it butโ€ฆ

They were acquired by Cloudflare and Deno Deploy was set to shut down.

I took this as a good time to get off the SSR + cache system I'd created on Deno + KV, and get closer to what my site actually was, a mostly static site.

I picked Astro + Cloudflare. It's done, and you're reading this on it.

I've always liked Cloudflare, and I knew exactly which pieces I would use to support my site migration:

I'm sure Deno was basically spinning up equivalent services on Google Cloud, so now I'm saving money per month and even closer to the individual tools I needed to adopt.

The plan #

JAM, CDNs, SQLite, Cron

  1. Make the site static.
    Every page is built ahead of time, no server rendering.
  2. Keep the 3 dynamic bits alive in a tiny Worker.
    The anonymous like button, live view and like counts, and the social cron jobs.
  3. Put everything on Cloudflare.
    Cron, edge endpoints, D1 for likes and counts, R2 bucket for static assets.

Fresh โ†’ Astro #

The posts on my site, the core content, were markdown already.

Since Astro is rad, my Deno Fresh / Preact components were kept and are rendered inside Astro at build time. Kinda nice I didnt need to migrate my component model.

Most of the migration was spent porting Deno and Deno Deploy features to Cloudflare.

Stuff I juggled #

Deno KV migration: Likes and counts lived in KV. They moved to D1. I exported production's KV (about 1,900 entries) and imported it, so no counts reset.

911 MB of media: Way too much to ship with every deploy. It all moved to R2, and the Worker serves it from the same /media/* URLs, so no old link or embed breaks.

Crons: Deno.cron became Worker cron triggers. The social stats job got smarter on the way: fresh posts get checked often, old ones rarely, so it stays inside the platform's limits.

Analytics: Pirsch hits now fire from the Worker on the server side, so adblockers can't eat them.

A moving target: I kept writing posts and merging PRs mid-migration. Instead of freezing everything, a sync script replayed new commits onto the Astro tree, right up to the end.

Secrets: Some lived in Deno's dashboard and can't be read back out. I had to conjure freshies and set them on the Worker. Not hard, just annoying.

The cutover #

DNS switch went smooth. Just had to add the zone to Cloudflare, copy records, swap nameservers. I flipped them this morning, attached the custom domain to the Worker, and boop done.

I'll keep the Deno site up for a few days as a rollback. Plus, a couple old DNS caches will still hit it for a bit, so I'll reconcile any likes that landed there in the meantime. Maybe.

The results #

Thanks Deno, it was a good run.

  • Same site, pixel for pixel
  • Faster
  • Cheaper

๐Ÿฆ• โ†’ โ˜๏ธ

The forcing function worked out pretty good. Sometimes you need a good kick in the ass.