Skip to content

Database & Migrations

shrtnr uses Cloudflare D1 (SQLite-based) as its primary database, with a KV namespace for slug-lookup caching.

Binding

The database binding is defined in wrangler.jsonc:

jsonc
"d1_databases": [
  {
    "binding": "DB",
    "database_name": "shrtnr-db",
    "migrations_dir": "migrations",
    "database_id": "..."
  }
]
  • Binding name: DB
  • Database name: shrtnr-db
  • Migrations directory: migrations/

Applying migrations

bash
# Local development database
bun run db:migrate:local

# Remote (production) database
bun run db:migrate:remote

These are equivalent to:

bash
bunx wrangler d1 migrations apply DB --local
bunx wrangler d1 migrations apply DB --remote

Migrations are required after one-click deploy

Cloudflare one-click deploy does not copy GitHub Actions workflows, so it does not migrate automatically. After the initial deploy, run bun run db:migrate:remote immediately, otherwise the schema is missing and the app will not work. See Deploy.

Migration list

Migration files live in migrations/, named by sequence number and applied in order:

FileDescription
0001_initial.sqlInitial schema (links, slugs, etc.)
0002_analytics_schema.sqlClick analytics tables
0003_drop_cached_counters.sqlRemove cached counters
0004_slug_text_pk.sqlSlug switched to a text primary key
0005_bundles.sqlBundles support (later removed) and visitor fingerprint column
0006_self_referrer_flag.sqlSelf-referrer flag
0007_redirect_settings.sqlDynamic redirect rule settings
0008_pages.sqlCustom pages support
0009_drop_bundles.sqlRemove the bundles feature schema

Migration conventions

Data safety

  • Preserve all existing data.
  • When recreating a table referenced by ON DELETE CASCADE foreign keys, save and drop dependent tables first, then restore after rename.
  • Verify row counts are unchanged in all affected tables post-migration.

KV cache

Slug-to-link lookups are accelerated by the KV namespace SLUG_KV (bound in wrangler.jsonc), implemented in src/kv/slug-cache.ts. The namespace ID is resolved at deploy time by scripts/resolve-bindings.sh.

Released under the Apache License 2.0. Upstream built by Oddbit.