Upgrading & Migration

This page records the compatibility facts the code actually guarantees. Anything not verified by a test or an explicit version check is marked untested — verify before relying rather than claimed as a guarantee. Source: the repo's upgrading guide.

Always back up first. Take and relata verify-backup <path> a full snapshot before touching any node. Restore forward (old → new), not backward — backward format/version compatibility is untested.

Upgrading to 2.0.0

2.0.0 is a major release with breaking changes (semver-mandated by the Zero-Trust / licensing / tenancy work). Review before upgrading from 1.x:

  • Multi-tenant gating. RELATA_TENANCY_MODE=multi now FATALs on free and server (both fixed at max_tenants=1). Multi-tenant mode is cluster-only and requires an effective max_tenants > 1 (license value, or the RELATA_MAX_TENANTS override). If you ran multi on free/server in 1.x, move to cluster with a multi-tenant license or stay on single. See Deployment.
  • Licensing model v3. The binary "unlimited-storage" capability is gone. Licenses carry two numeric parameters on the signed NodeConfigstorage_max_gb and max_tenants (0 = unlimited). Re-issue licenses with the v3 tool; old .lic files without these fields are rejected. See Licensing & Tiers.
  • Zero-Trust admin surface. /admin/* and /platform/* moved to a separate loopbound listener (RELATA_ADMIN_BIND, default 127.0.0.1:9091); they are no longer served on RELATA_HTTP_BIND. Set RELATA_ADMIN_TOKEN and reach the surface via port-forward / sidecar.
  • Auth posture uniform. No more implicit free-profile dev bypass — set RELATA_OPEN_DEV_ALLOWED=true explicitly for unauthenticated local dev, on every profile.
  • Go SDK → github.com/relatadb/sdk-go/v2. The major-version import-path suffix is mandatory; update your imports. See SDKs.
  • Version lockstep. Server and all SDKs/tray/Grafana/Helm now ship one version, enforced by the repo's check_versions.py.

Validate on a staging copy of your data first; back up before upgrading.

On-disk / artefact format compatibility

Manifest (object-store layout)

relata-storage::manifest::ManifestVersion is the source of truth for the commit-manifest layout. Two variants exist: V1Single (legacy single file) and V2Sharded (sharded layout) — new writes always emit V2Sharded. Readers detect the version from the index object. There is no in-place V1→V2 rewriter; the migration story for an existing V1 store is untested — verify before relying (prefer a fresh V2 store seeded from a restore over an in-place flip).

Backup snapshot format

relata-storage::backup::BackupPayload is a self-describing JSON artefact (full-<ts>.json / incr-<ts>.json) with schema_version: u32 (currently 1). Cross-tenant restores are enforced (assert_agency aborts a payload/organisation mismatch). Tenant-scoped restore (POST /admin/restore {"tenant": "..."}) is rejected outright (501) — the store-swap is an unconditional whole-store replacement, so a tenant-scoped request would silently wipe every other tenant. Restore only without a tenant field until a true per-tenant merge ships.

Restoring a backup taken by a newer build into an older binary is untested — verify before relying. Always run relata verify-backup <path> before depending on a snapshot.

Ontology version monotonicity

relata-ontology::OntologyVersion(u64) is a monotonically-increasing counter, bumped on every type addition/modification and stored in the commit manifest. The version only ever moves forward within a branch; it never rewrites history. Downgrading the binary does not roll the ontology version back — an older binary reading a higher ontology version is untested — verify before relying.

Rolling-upgrade ordering (recommendation)

This ordering is a recommendation, not an enforced/tested invariant:

  1. Back up first — take and verify-backup a full snapshot before touching any node.
  2. Validate config — the CLI fails fast (exit 78, EX_CONFIG) on an invalid RELATA_* enum/numeric value. Apply config changes to one node and confirm it starts clean before rolling out.
  3. Upgrade followers before the coordinator/writer — in a cluster, roll reader/follower nodes first so the write path stays on the known-good version longest; promote the coordinator/writer last.
  4. cluster profile only — drain the node before stopping it. Run relata cluster drain <node-id> --wait and confirm safe_to_stop: true before deleting/restarting a writer's pod. Otherwise the passive heartbeat-timeout rebalancer (RELATA_CLUSTER_DEAD_AFTER_SECS, default 90 s) may evict and re-move partitions during a slow restart — real, avoidable data movement.
  5. One pod at a time — the operator's StatefulSet uses RollingUpdate (default one pod at a time, or spec.upgrade.maxUnavailable). Wait for GET /health/ready 200 and (cluster) for relata_replication_lag_seconds to settle before continuing.
  6. Roll back by restoring, not by downgrading in place — backward format/version compatibility is untested.

Config migration

relata config --migrate          # migrate relata.toml / env vars across versions

The CLI now fails fast on invalid RELATA_* enum/numeric values and logs the offending variable, so config drift surfaces at startup rather than at runtime.

Data migration

PathWhenDocs
relata import --from postgres|csvMigrate an existing database into RelataConnectors & Extensions · Ingestion
relata config --migrateMigrate config across versionsabove
Embedding-model migrationChange the sidecar model / vector dimensionLLM & Embedding configuration
Backup → restoreWhole-store migration / disaster recoveryBackup & Restore

For Neo4j / MongoDB / ClickHouse, relata import --from <source> is an honest stub today — each prints the documented CSV/NDJSON export workaround and exits non-zero.

v1.4.2 → v1.5.0 (reference)

A backward-compatible upgrade. /query responses added processing_time_ms alongside elapsed_ms (the latter retained for one release, removed in v1.6.0). QueryError exposed stable REL_* codes; the RFC 7807 type URI changed from about:blank to https://relatadb.dev/errors/{code}. 429 responses added X-RateLimit-* headers. Admission control moved to a real cost estimate (row count × join multiplier). Rolling: upgrade reader/indexer nodes first, writers last; all in-flight writes are safe (formats compatible).

See also