Skip to main content

8 posts tagged with "foundation"

View All Tags

Live Admin With Gleam and Lustre

· 11 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Curling IO's admin panel should feel instant when a club manager is working through a season setup. Toggle a setting, save a discount, move between product sections: the page should respond without a full reload.

Version 2 works, but every form submission reloads the page. Version 3's admin is a single Lustre server component running on the BEAM. One WebSocket connection, one long-lived Erlang process per session. Every interaction goes over that WebSocket and comes back as a DOM patch. The page never reloads, and there's no client-side JavaScript framework.

Parallel Tests for Free

· 5 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

While writing the previous post about our per-test SQLite databases, I was describing how each test gets its own in-memory database, no shared connections, no shared state. And I thought: wait, if nothing is shared, can we just run them all at the same time?

Turns out we could, and our server test suite went from ~4 seconds to ~0.85 seconds for around 800 tests. Zero code changes to the tests themselves. One 25-line Erlang module.

Test Isolation for Free with SQLite

· 9 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Curling IO's tests don't need a shared test database, cleanup hooks, or transaction tricks. Each test gets its own database, so a test can pass alone or in the full suite for the same reason: nothing else can touch its data.

That falls out of one Version 3 choice: SQLite runs in-process. Each test gets a completely independent in-memory SQLite database, cloned from a template in microseconds using SQLite's backup API.

Why We Chose SQLite

· 11 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Version 3 should be cheaper to operate, easier to restore, and still fast during peak registration and live scoring. That pushed us toward a choice we didn't expect: SQLite.

We assumed PostgreSQL at first. After a decade running Postgres in production, we knew the tooling, the failure modes, and the operational playbook. Then we compared self-hosting Postgres with Litestream-backed SQLite and changed our minds.

Background Jobs Without the Baggage

· 6 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

When a curler asks for a login email, the page should respond immediately. They shouldn't wait on Postmark, and we shouldn't run a separate worker fleet just to send a message in the background.

Curling IO Version 3 runs background jobs inside the same BEAM runtime as the web app. No Redis. No separate worker. No additional deployment. The queue is durable because pending jobs live in SQLite, not memory.

Passwordless Auth, Done Right

· 11 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Curling IO has been passwordless since Version 2. No passwords to remember, no passwords to steal, no password reset flows. You enter your email, we send you a short-lived login code, and you're in. It's been working well for over a decade, and for Version 3 we're keeping the same approach while fixing some rough edges and adding multi-email support.

But first, let's talk about why we made this controversial decision in the first place.

Bilingual by Design

· 7 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

English and French support has to be boring. A club in Quebec shouldn't find a half-translated registration page, and a national organization like Curling Canada shouldn't need a support ticket to catch a missing label.

Curling IO has been bilingual since Version 2, but after a decade of maintaining around 10,000 YAML translation keys, we've hit the limits of what that approach can catch: missing keys, missing translations, and unused keys that accumulate silently over time. Version 3 keeps the bilingual experience and makes more of those mistakes impossible to ship.

The Next Version of Curling IO

· 7 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

The next version of Curling IO should feel familiar: the same registrations, schedules, scoring, and club admin workflows, just faster and harder to break. The work is mostly under the surface, but the payoff is practical: fewer slowdowns at peak registration, better reliability during live events, and a platform we can keep improving for a long time.

This series explains what changes, what doesn't, and why we're making the bet.