Skip to content

Upgrade

The product is now Pitot (pronounced PEE-toh), formerly Fanout, at pitot.dev. The owner approved this rename on 2026-11-11 to avoid a conflict with a third party’s registered US trademark in cloud services.

  • The Go module is github.com/labstack/pitot; the binary is pitot and native archives are pitot_<version>_<os>_<arch>.tar.gz, containing ./pitot.
  • Container images are ghcr.io/labstack/pitot and docker.io/labstack/pitot. Update deployment manifests, service names, install URLs and MCP client entries. The MCP Registry identity is io.github.labstack/pitot.
  • Use PITOT_* settings. For the first Pitot alpha only, an unset primary variable falls back to its FANOUT_* equivalent, including secret _FILE forms and installer version/prefix overrides. A primary variable explicitly set to empty blocks its legacy equivalent and uses the ordinary default. Startup emits one deprecation warning listing used old names, never values. Mixed value/file forms still fail when both are nonempty. Replace old names before upgrading to the following alpha, when this bridge is due for removal.
  • Keep the complete existing data directory. Native default ./data, the control/fanout.sqlite filename, all other storage filenames, telemetry format, marker files, Parquet fanout.spill.* footer keys, stored _fanout_diagnostic_context metadata and published migrations are unchanged; there is no data migration. The new image defaults to /var/lib/pitot/data: mount the existing volume there, or explicitly set PITOT_DATA_DIR to its existing mount location. Do not accidentally create a fresh named volume when changing deployment names.
  • Existing sessions keep their cookie names and keyboard preferences keep their storage key. Saved chat activities resolve their old MCP App resource URI to the new URI in memory, without rewriting history. Existing ingest and OAuth secrets remain valid; token prefixes (foi_, foa_, for_, foc_) are unchanged for both existing and new tokens because there is no central token-prefix registry.
  • HTTP request headers and metrics use the Pitot name. Update custom clients using the product request header to Pitot-Request (and dashboard deletion confirmation to Pitot-Confirm-Delete), and update Prometheus queries and alert rules from the old metric prefix to pitot_.

Take a cold backup before upgrading, stop the old service, replace the binary or image, and start the new service against the same data and secrets. Verify /readyz, sign-in, ingest and a representative query before resuming traffic.

Pitot versions are CalVer tags, vYYYY.M.N with an optional maturity suffix. N counts every release in the month, whatever its suffix. Container image tags omit the leading v: release v2026.9.5 is image tag 2026.9.5.

TagChannelExample
No suffixStablev2026.9.5
-rcPrerelease: release candidatev2026.9.4-rc
-betaPrereleasev2026.9.2-beta
-alphaPrereleasev2026.9.0-alpha

The tag of each GitHub Release shows its channel.

Every release, stable or prerelease, is a full GitHub Release with the same contents: Linux and macOS archives for amd64 and arm64, a SHA256SUMS file, GitHub build-provenance attestations for each archive and for SHA256SUMS, and a multi-architecture image on GHCR with a Docker Hub mirror of the same digest. Releases shows how to verify them. Fix a problem in a published version with a new release number, never by replacing that version. A version’s image tag can still be pushed again, so record the digest you deploy and compare it with the one published for the release.

The latest image tag and the installer’s default follow the newest release of either channel. They are not a stable channel. To run stable releases only, pin a release tag without a suffix (image tag 2026.9.5 for v2026.9.5), or the image digest it resolves to, and upgrade deliberately.

Each GitHub Release starts with an Upgrade notes section. The release workflow writes it by comparing the tag with the previous published release. A tag whose release workflow failed has no release and is skipped, so its changes are reported by the next published release:

  • Format change: batch format X to Y (a caution callout) marks a release that cannot read telemetry written by earlier releases. Follow when a release changes the batch format.
  • Control schema migration lists the control database migrations the release adds. They run forward at startup, so rolling back means restoring a backup.
  • Storage states that the batch format is unchanged and no migrations were added, so a missing marker is never ambiguous.
  • Breaking changes lists the merged changes whose titles carry the Conventional Commits ! marker, for example feat(auth)!:.

Maintainers add any manual steps below these markers. The markers compare each release only with the one before it. When you skip releases, read the notes of every release between your version and the target.

A release without a generated section predates it. Its notes are handwritten; read them for the same changes. For example, v2026.11.0-alpha changes the batch format from 4 to 5.

A breaking change is one that needs action from an operator or client after upgrading. That includes removing or renaming an HTTP route, a JSON field or query parameter, an MCP tool or its arguments, or a configuration variable; changing a credential format; and changing the batch format.

  • Prereleases may ship a breaking change in any release, without notice. The release’s upgrade notes mark it.
  • Stable releases announce a breaking change in the notes of an earlier stable release at least 30 days before a stable release ships it. The announcement names what changes, its replacement, and the earliest release that may change it.

Additions are not breaking: new routes, tools, optional fields and settings can appear in any release.

Pitot does not serve an old and a new name side by side. A rename or removal changes the route registration, its clients, its authorization and the generated HTTP routes and MCP tools reference in one release, with no alias or fallback.

Deprecation is therefore a notice, not a transition period:

  1. A stable release’s upgrade notes announce the deprecated route, field, tool or setting, with its replacement and the earliest release that removes it.
  2. Until that release, the deprecated contract keeps working unchanged.
  3. The removing release lists the change under Breaking changes.

Protocol-defined contracts follow their own specifications rather than this schedule: OTLP ingest, the MCP protocol, OAuth and the /.well-known metadata paths. Product CalVer never appears in API paths or MCP tool names.

  1. Read the target GitHub Release and every release you are skipping, and pin the target’s binary or image tag.
  2. Take and verify a cold backup. Record the running version with it.
  3. Stop Pitot and wait for it to exit.
  4. Replace the binary or image. Keep the data directory unless the release requires the format-change procedure below.
  5. Start Pitot. Check /readyz, sign-in, configured OTLP transports and representative queries.

Pending control SQLite migrations run forward, in order, at startup, so one upgrade can cross several releases. Migrations have no down path. A rollback after migration is not assumed safe.

Restore a backup only with the version that created it. Pitot does not record which release wrote a data directory, so it cannot warn about a mismatch:

  • A release reads only its own batch format and refuses to start on any other.
  • An earlier release is not designed to run against a control database that a later release migrated.

To roll back, stop Pitot, restore the complete pre-upgrade backup, and start the previous binary or image. To move to a newer version after a restore, verify the restored instance first, then upgrade with the steps above. See back up and restore.

v2026.11.0-alpha requires batch format 5 and cannot read format 4. For that upgrade, and any release whose notes carry a Format change marker:

  1. Stop Pitot and take a complete cold backup.
  2. Move telemetry/ and query/ out of the data directory. Keep them together for recovery with the previous version.
  3. Keep control/ in place. It preserves users, dashboards, alert rules and the ingest token.
  4. Install the target binary or image and start Pitot with the same data directory setting.
  5. Verify readiness and sign-in, then send new telemetry and check a query.

Old telemetry is unavailable in the upgraded instance. Query state rebuilds from the new telemetry. Do not copy unsupported batches back into it. See storage for the current format contract.

v2026.11.0-alpha also renames API and MCP contracts without aliases. Update scripts and clients using the release notes and HTTP routes.

Ingest tokens use the foi_ prefix. Pitot rejects tokens issued with the earlier fo_ prefix. After upgrading, an administrator creates a token in Connect telemetry → Ingest tokens and updates every collector. Unused login links issued before the upgrade stop working; request a new one. Connected MCP agents keep their OAuth tokens.

The single stored ingest token becomes a token named default with its digest unchanged, so running Collectors keep working. POST /api/settings/ingest/token/rotate is removed; rotate by creating a token with POST /api/settings/ingest/tokens and revoking the old one with POST /api/settings/ingest/tokens/{id}/revoke. PITOT_INGEST_TOKEN applies only when no token has ever existed, so leaving it set is harmless and it cannot restore a revoked token.