Relayer logoRelayer

Concepts

Apps, channels, releases, rollouts and devices: the Relayer data model.

App

One piece of software you ship. An app has a display name (rename any time) and an immutable 16-character ref used in every URL and API call - so renaming never breaks shipped devices.

Channel

A distribution track: stable and beta exist by default; add more (internal, canary, …) freely. Devices ask for updates on exactly one channel. Each channel can carry a policy: a minimum supported version and an update mode - devices below the minimum receive updates flagged required.

Release

An immutable version published to a channel: version string, markdown release notes, and a list of artifacts (platform, arch, URL, sha512, size, optional code-signing signature). Relayer never stores your binaries - artifact URLs point at your existing storage.

A release has a status:

  • published - servable.
  • paused - temporarily not served; resume any time.
  • rolled_back - permanently withdrawn (cannot be resumed; publish a new version instead). Devices already ON it are served the newest published release below it as a downgrade (allowDowngrade).
  • deprecated - end of life. Not served, but reversible (it is a policy, not an incident). Devices still on it are never downgraded - instead, the next update they are offered arrives with updateMode: required, the mirror of the rollback rule.

It can also carry targeting - rules restricting which devices are eligible - and a rollout percentage ramping how many of those devices are offered it. Targeting has two parts, ANDed together:

  • matchLabels - exact-match label rules: AND across keys, any-of within a key's values.
  • matchExpressions - decision-time predicates: { key, operator, values } with operators In, NotIn, Exists, DoesNotExist, plus semver-aware VersionGte / VersionLt on the reserved $version key. Keys resolve against device labels, or against the request itself via $version, $platform and $arch - so "serve only devices below 2.0 on macOS" needs zero client changes. Every operator except DoesNotExist fails closed when its key cannot be resolved.

After a release's first offer, labels may only broaden - and expressions are frozen entirely (change them by cutting a new release). Full semantics, operators and examples: Targeting.

How serving decides (the mental model)

Relayer never pushes bytes. A device (or an orchestrator acting for it) asks "I am X, running Y - what should I do?", and ONE decision function answers - the same function behind /u/, the push-mode batch endpoint, the electron feed, and the dashboard's "Why this update?" preview. They share code, so the preview cannot disagree with production.

The walk: take every release in the device's channel, newest first, and find the first one that passes all five checks:

  1. Newer than the device's current version (else: up to date, stop).
  2. Published - paused, deprecated and rolled-back releases are skipped.
  3. Targeting matches - the device must satisfy every label rule (any-of within a key) AND every match expression. Devices that cannot satisfy a rule fail closed and skip the release.
  4. In the rollout - sha256(deviceId:releaseId) % 100 < rolloutPct. Deterministic, so cohorts are sticky between checks.
  5. Artifact exists for the device's platform/arch.

The property that makes this safe: a skip is never a dead end. A device outside a 10% rollout or a canary target falls through to the newest release below that it IS eligible for - excluding a device from the new thing never breaks its update path.

One exception to rule 1: if the device's current version was rolled back, the walk continues below it and serves a downgrade - a pulled build should never silently keep its victims.

Two invariants keep the dashboard honest, and both engage at the same moment: the first real offer. Until a release has been offered, rollout percentage and targeting are just a plan - edit them freely. Once offered, the percentage only increases (buckets are sticky, so decreasing never un-serves anyone - pause to halt, roll back to pull) and targeting only broadens (broadening is itself permanent).

Rollout percentage

Every release has a rollout percentage (default 100). At 25%, only a quarter of eligible devices are offered that version - and when the release is targeted, the percentage applies within the targeted cohort. "On this version" on the Releases tab counts what devices actually report running; offers always lead installs.

Device

An installation of your app, identified by an anonymous UUID that your app generates and stores locally, sent in the X-Relayer-Device header. No accounts, no PII. Every update check records version, platform, arch and timestamp - that's the fleet dataset behind the dashboard.

Devices don't have to check in themselves: an orchestrator can report state and plan update waves on their behalf via the push-mode fleet API, optionally attaching labels - opaque key/values (customerRef, siteRef, …) that Relayer stores and echoes but never interprets.

Organization

The workspace everything lives in: apps, keys, devices and the audit log are organization-scoped, and teammates hold roles (owner / admin / member) within it. See Organizations & roles.

Audit log

Append-only record of every mutation - publishes, rollout changes, key mints, webhook deliveries - with actor, IP and timestamp. Mutations that cannot be audited do not happen.

On this page