Skip to content

Schema Versioning Guide

spanforge events carry a schema_version field (semver) that governs backward and forward compatibility.


Version field

Every event envelope includes:

{
  "schema_version": "2.0",
  ...
}

The current stable schema version is 2.0.


Compatibility rules

Change typeVersion bumpProducerConsumer
Add optional field to envelopeMINORMAY addMUST ignore unknown fields
Add optional field to namespace payloadMINORMAY addMUST ignore unknown fields
Add new namespaceMINORMAY emitMUST accept (payload opaque)
Rename or remove fieldMAJORMUST bumpMUST handle both until old major is sunset
Change field typeMAJORMUST bump
Add required fieldMAJORMUST bump

Rule of thumb: Consumers must be written to tolerate new fields (forward-compatible reads). Producers must never remove or rename fields within the same major version.


Migration between major versions

v1 → v2

The v2 schema has shipped (SCHEMA_VERSION = "2.0"):

  1. Both schema_version: "1.x" and schema_version: "2.x" events will be valid during the transition window (minimum 6 months)
  2. The spanforge migrate CLI command will convert v1 JSONL archives to v2
  3. A compat shim module will be provided in the SDK

Checking schema version at runtime

import spanforge

event = spanforge.Event.from_dict(raw_event_dict)

major = int(event.schema_version.split(".")[0])
if major > int(spanforge.SCHEMA_VERSION.split(".")[0]):
    raise ValueError(f"Unsupported schema major version: {major}")

Or use the CLI:

spanforge check-compat events.json

Namespace versioning

Namespaces themselves are versioned independently via the RFC amendment process (see RFC-0001):

  • New namespaces are added in MINOR schema bumps
  • Existing namespace payload shapes only change in MAJOR bumps

Pinning to a schema version

If your consumer must only process events from a specific schema version range:

import spanforge
from spanforge import Event

def process(raw: dict) -> None:
    event = Event.from_dict(raw)
    if not event.schema_version.startswith("1."):
        raise ValueError("Only schema v1.x supported")
    # ... process

See also