New Jun 20, 2025

Ditching Deno KV

More Front-end Bloggers All from dbushell.com (blog) View Ditching Deno KV on dbushell.com

Way back in 2021 I began the adventure of building my own media server for audiobooks and podcasts with a PWA front-end. This side project has taking me on a tech rollercoaster. The only waste of time has been Deno KV and one episode of the All-In podcast I suffered through desperately hoping it was a parody.

I’ve done a bad job tracking development but I’ll attempt a brief history:

Dev Timeline

v1 was bootstrapped with an embarrassingly hacky SQLite interface. My solution stress tested the phrase ā€œit ain’t stupid if it worksā€. If you can figure out what I was doing, just know that I was fully aware of how stupid it was! It’s remarkable how ā€œtemporaryā€ turns into technical debt so quickly.

v2 was a major rebuild with SvelteKit. I made a custom API that dropped Subsonic compatibility. I used a proper SQLite module. I later changed the podcast syncing to use a 3rd-party index. That proved unreliable so I did the unthinkable and parsed XML myself.

v3 was another major refactor (I’m losing track). I dropped SvelteKit in favour of my own scuffed library and HTMX inspired web components. On a fateful whim I replaced SQLite with Deno KV. I refreshed the design too.

Along this journey I’ve learnt: natural sorting, relative formatting, media session, file storage, off-screen canvas, and so much more. Including the fact that not a single person on earth is capable of publishing a valid and logical RSS feed (I blogged one of many issues).

RIP Deno KV

In April I wrote about Deno’s Decline. My post topped ā€œthe usual placesā€ and elicited an official response. I wasn’t acknowledged directly, but no one else was blogging about Deno. I’d have enjoyed a shoutout but either way it doesn’t look good. Dahl’s update confirmed that Deno KV is dead without saying it out loud (VCs spook easily).

SQLite Lives

This left me two options:

  1. Remain on Deno KV
  2. Return to SQLite

Option one was a valid choice. KV still works and I’m fully self-hosted. Option two would allow me to attempt SQLite again (third time’s a charm). I’ve since gained more tools from building several SvelteKit apps. This time I’d use Arktype and Drizzle instead of stubbornly hand-rolling SQL.

Due to the aforementioned RSS feed woes, my ā€˜perfect’ KV architecture was suffering a few setbacks. I wrongly assumed 3rd-party data would be in any shape coherent. How naive I was. I can’t blame Deno for that! New KV APIs might have presented better solutions, but with KV shelved I chose option two.

One architectural success I made was wrapping the database in a CRUD-like API. This provided functions like getPodcast and deleteEpisode — simple stuff.

I first rewrote podcast related functions backed by SQLite. Then work got busy for weeks, leaving me with an app running off two databases. I awoke at 5am today to finish the job for audiobooks. The most rewarding part of this update was the migration script:

import * as kv from "./src/kv/mod.ts";
import * as db from "./src/sqlite/mod.ts";

for (const podcast of await kv.getPodcasts()) {
  await db.setPodcast(podcast);
  for (const episode of await kv.getEpisodes(podcast.id)) {
    await db.setEpisode(episode);
  }
}

The script iterated over entities from the old KV database and inserts then into the new SQLite database. The power of abstraction!

In hindsight Deno KV was a bad bet. You live and learn. This is why I experiment on personal projects and not client work. sauroPod is on GitHub if you fancy a look. Despite the Docker file it won’t run on your machine without undocumented extras. Maybe one day when I’m done refactoring I’ll release a usable version.

So long Deno KV 🫔 you served me well(-ish).

Scroll to top