Skip to main content

Custom Registration Forms Are Coming to Curling IO

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

This post is part of our Curling IO v3 sneak peek series, where we explore some of the new features available in the upcoming version.

Registration forms in Curling IO have always collected the basics: team name, lineup, skill level, contact info. But every club runs things a little differently. Some need emergency contacts. Others want dietary restrictions for banquet planning. A bonspiel might ask for team contact information while a league doesn't.

In v2, admins can already choose which questions appear and create custom ones. What's new in v3 is control over the layout: where each question sits, how wide it is, and how the form is organized into sections.

Live Admin With Gleam and Lustre

· 11 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO
About this post

This is a technical architecture post from the development of Curling IO v3. It is written for software engineers and goes deeper into Gleam, Lustre, the BEAM, WebSockets, and server-rendered interfaces than our usual product posts.

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.

AI Agents Love Gleam

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

Fair warning: this post contains some opinions that are going to be controversial and may not age well. Here be dragons.

AI coding agents like Claude Code, OpenAI Codex, and Google Gemini can write code, run it, read the errors, and try again. That loop is the whole game. The faster and more informative that loop is, the more useful the agent becomes. After building Curling IO Version 3 in Gleam alongside AI coding agents, I'm convinced Gleam is the best language for this workflow. Agents don't write better Gleam - there's less training data. But Gleam's compiler lets agents self-correct without waiting for a human.

Parallel Tests for Free

· 6 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO
About this post

This is a technical implementation note from the development of Curling IO v3. It is written for software engineers and goes deeper into Gleam, Erlang, EUnit, test isolation, and parallel execution than our usual product posts.

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
About this post

This is a technical implementation note about the testing architecture for Curling IO v3. It is written for software engineers and goes deeper into SQLite, in-memory databases, the backup API, and test isolation than our usual product posts.

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
About this post

This is a technical architecture note about the database decision for Curling IO v3. It is written for software engineers and operators, and goes deeper into SQLite, Litestream, database isolation, hosting, and recovery tradeoffs than our usual product posts.

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.

Built for High-Traffic Curling Competitions

· 2 min read
Chris
Chris
Product @ Curling IO

Major curling competitions put very different demands on software than a typical league night. Registration can involve qualification rules and team assembly, draw schedules need to cover multiple pools and playoff formats, and live scoring traffic can spike as thousands of fans follow the same games.

Background Jobs Without the Baggage

· 7 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO
About this post

This is a technical implementation note from the development of Curling IO v3. It is written for software engineers and goes deeper into Gleam, the BEAM, OTP, SQLite-backed queues, durability, and job execution than our usual product posts.

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.