How PitchRoots is built

PitchRoots looks like a news feed with a games calendar attached, and to read it, it is. Underneath, it's a small but complete example of something called durable execution — and since the whole thing is public and easy to follow, it doubles as a working demonstration of durable execution.

Two loops, one database

There are two independent halves that never talk to each other directly. A write loop runs in the background on a schedule, gathering and summarizing the news and keeping the games calendar current. A read loop serves the website. They meet only at a shared database.

  WRITE LOOP  (durable, in the background)   READ LOOP  (every visit)
  ────────────────────────────────────────   ────────────────────────
  pg_cron ── every hour                      you → pitchroots.ca
       │                                          │
       ▼                                     served from the CDN
  poll()  ── a durable workflow                   ▲
       │                                          │  (re-rendered from the
       ├─ fetch each feed                         │   database on a timer, or
       ├─ verify every link                       │   right after new items
       ├─ classify + summarize (AI)               │   are published)
       └─ save new items ─────────────┐           │
                                      │           │
  pg_cron ── every day                │           │
       │                              │           │
       ▼                              │           │
  pollGames()  ── a durable workflow  │           │
       ├─ fetch the box office        │           │
       └─ save every upcoming game ───┤           │
                                      ▼           │
  ┌──────────────────────────────────────────────────────────────────┐
  │  one Postgres database                                           │
  │    · the articles   · the games   · the durable-execution engine │
  └──────────────────────────────────────────────────────────────────┘

Because all the expensive work happens ahead of time in the write loop, the website itself never calls an AI model or fetches a feed while you're looking at it. It just hands you a page that was already built. That's why it's fast, and why it costs almost nothing to run.

The hourly job, step by step

Every hour, one durable workflow runs, once per news source, and does this:

  1. Fetch the source's feed.
  2. Skip anything already seen or already rejected — before spending anything on it.
  3. Verify the link actually resolves, following redirects and dropping dead ones, so the feed never points at a 404.
  4. Classify and summarize what's left with a language model — deciding whether it's Canadian soccer, which topics it touches, and writing a one- or two-sentence summary in original words.
  5. Save the relevant items, and record the dead links and rejected articles so future runs skip them without asking the AI again.

What “durable” means here

Each of those steps is checkpointed to the database the moment it finishes. If the job is interrupted partway — a timeout, a crash, a redeploy — it doesn't start over. It resumes from the last completed step. A feed already fetched isn't fetched again; an article already summarized isn't sent to the AI a second time. The work-in-progress lives in the database, not in the memory of a program that might disappear.

The precise guarantee is exactly-once checkpointing with at-least-once side effects — a step can run again, but it can never leave a duplicate behind, because every save is written to be safely repeatable.

A second workflow: the games calendar

The games calendar is filled in by a second durable workflow, running once a day on the same engine inside the same database. It asks the box office — Ticketmaster's public events listing — for every upcoming soccer event in Canada, sorts what comes back into competitions, and saves each game under the box office's own id for it. Fixtures move, so a rescheduled kickoff, a new venue, or a cancellation simply overwrites the row on the next sync, and a step that runs twice writes the same values twice.

There is no AI in that job at all — the listings arrive structured, and working out that one of them is a CPL home game is ordinary code. Same machinery, a different problem: durability is about surviving interruption around calls to the outside world, and the language model in the news pipeline is incidental to it.

The unusual part: no separate server

Normally, durable execution needs its own workflow server running somewhere. PitchRoots doesn't have one. The entire engine — resonate-pg — is a single SQL file that runs inside the same Postgres database that stores the articles. Postgres itself keeps time and triggers the hourly run. So the whole system is really just a static website and a database — with the reliability of a workflow engine folded into the database itself.

This is all built on Resonate durable execution. If you're curious about the machinery, the source is public.

← Back to the feed