Skip to content

1.7.0

Latest

Choose a tag to compare

@sjdonado sjdonado released this 05 Oct 16:58
9e5ec75

Highlights

  • About 6x faster redirects. SQLite now runs in WAL mode with synchronous=NORMAL, as the database URL always intended; the old SQLite driver ignored those settings. The benchmark went from about 3.5k to 21k req/s with every click recorded, at 6 ms average latency and 32 MiB average memory (benchmark).
  • Security fixes. Crystal 1.21.1 fixes HTTP request smuggling and request body handling in the standard library server, and Kemal 1.14 fixes, among others, HEAD requests bypassing GET filters and route matching on malformed methods.
  • Official multi-arch image. The image is built from the official Crystal 1.21.1 Alpine image for linux/amd64 and linux/arm64.
  • Safer migrations. Micrate is replaced by a built-in migrator that keeps the same micrate_db_version history, stops the app when a migration fails, and adds cli --migrate-down to roll back the newest migration.
  • Tested data updates. The scheduled GeoLite2 and user-agent regex update now runs the full test suite against the downloaded files before it opens a PR.
  • Redirects keep visitor metadata out of caches, malformed API input gets controlled 400 responses, and repeated user-agent and GeoIP lookups are cached.

Upgrade notes

  • Back up sqlite/data.db before upgrading. On first start the database switches to WAL mode, and data.db-wal and data.db-shm files appear next to it. Mount the whole sqlite/ directory, as the Docker Compose file does, not only data.db.
  • Foreign keys are now enforced. Deleting a user now also deletes their links and clicks, as the schema always declared.
  • API errors are always JSON. A path with no route returns 404 {"error":"Resource not found"} instead of an HTML page, and a wrong method returns 405 with an Allow header instead of 404.
  • Rollback is limited. cli --migrate-down refuses 20250319192003, which has no Down section. The image applies pending migrations again on its next start, so a rollback only sticks if you deploy an older image afterwards.
  • A database still older than March 2025 that holds clicks or links whose parent row is gone cannot run the 20250319192003 migration, as before this release.

What's Changed

  • Harden redirects, improve throughput, and add e2e coverage by @sjdonado in #21
  • chore: Update UA regexes and GeoLite2 database by @github-actions[bot] in #22
  • Upgrade Crystal 1.21.1, kemal 1.14, sqlite3 0.23, and fix parser CI by @sjdonado in #24
  • Bump version to 1.7.0 and test parser updates by @sjdonado in #25

Full Changelog: 1.6.2...1.7.0