Browse docsDevelopers

Warm pools

What a watched ref keeps warm, how a claim takes from it, and when it drains and rewarms.

updated 2026-10-06

A warm pool is what a watched ref keeps: n VMs built at its head and parked, so a claim is instant. This page is the reference for the pool model, the claim, the drain, and what rift_repos shows.

The model

A pool is keyed by repository and ref. It knows its desired count — the warm you gave rift_watch, one by default — and its head, the commit Rift last heard for the ref. Its members are VMs, each stamped with the commit and the image it was built from.

Each time something changes for a pool — its head or count, a member's state, the image, a claim — it launches what it is short of: parked and warming members at the head and on the current image, up to desired. A pool of three fills at once. Members over the count, and members at an old head or image, are drained.

The head

Rift learns a ref's head two ways: it asks GitHub when the ref is first watched, and GitHub's push webhook tells it every time after. A ref whose head Rift hasn't heard shows as head not known yet in rift_repos and as ref head pending in the app, and its pool warms nothing until it does.

When the head moves, members at the old commit are drained: destroyed once nobody claims them, while the pool warms new ones at the new head. A VM an agent holds is not a member any more and isn't touched.

The claim

rift_vm_new asks the pool for a VM:

  1. A parked member at the head, built on the current image, is popped: it resumes and is the agent's. It receives no secret: a verb fetches its credential per run. Instant, or as near as a resume gets.
  2. Otherwise the claim launches cold: a fresh VM goes through provisioning and warming for this claim alone, and rift_vm_new waits up to 30 seconds before answering with the status it's at.

A claim never changes who pays or owns what; the pool's VMs were the organization's, and the claimed one is the user's for the life of its task. After a claim, the pool is one short and refills at once.

Failures

When a VM fails to warm — the build broke, a deadline passed, the provider said no — the pool records it against the head. rift_repos shows the reason for the head it happened at, and how many rounds in a row failed. Rift doesn't hammer a broken head: after the first failed round a relaunch waits 30 seconds, and twice as long after each round in a row that fails, up to 10 minutes — or the next push, whichever is first. A VM that warms at the head clears the count.

Images

VMs are built on Rift's bootstrap image, and the pool remembers which. Rift sets the current image when it starts, and every pool learns it at once. A member on an image that isn't the current one is drained exactly like one at a stale commit, so a new image reaches every pool on its own. Until a pool knows the current image, it launches nothing, and a claim waits for the image: the pool decides it as soon as the image comes.

Unwatch

Unwatching a ref drains its pool: every parked member is destroyed and nothing is warmed again until the ref is watched anew. Claimed VMs on the ref run on until their tasks close. A claim on a ref that isn't watched is refused, and the refusal asks for watching to be enabled.

What rift_repos shows

text
rift_repos  acme-inc

For each watched ref of each repository: its warm count; how many VMs are ready — parked members at the head, on the current image, not draining; its head; and, when the last VM at the head failed, the reason and how many rounds in a row failed. The app's Repositories page shows the same. See Watch a ref for the steps.