Skip to content

Schema Lock

The ion.lock.json file pins wire-format contracts to prevent accidental breaking changes between services.

Why Schema Locks?

In distributed systems, multiple services share the same message definitions. If one team reorders a field, every service reading that field by index will misinterpret the data. Schema locks enforce that:

  • Field indices don't change (index = wire identity)
  • Field types don't change (encoding must be compatible)
  • Method signatures are stable
  • Enum/flags values are preserved
  • Union case ordering stays fixed (discriminator identity)

Lock File Structure

{
  "version": 1,
  "module": "MyProject",
  "definitions": {
    "User": {
      "kind": "msg",
      "nextIndex": 3,
      "fields": [
        { "index": 0, "name": "id", "type": "u4" },
        { "index": 1, "name": "name", "type": "string" },
        { "index": 2, "name": "email", "type": "Maybe" }
      ]
    },
    "UserService": {
      "kind": "service",
      "methods": {
        "GetUser": {
          "args": [
            { "index": 0, "name": "userId", "type": "u4" }
          ],
          "returns": "User",
          "modifiers": []
        }
      }
    },
    "Status": {
      "kind": "enum",
      "members": [
        { "name": "Active", "value": 0 },
        { "name": "Inactive", "value": 1 }
      ]
    }
  }
}

What Gets Locked

Element Locked Property
msg Field order (indices), field names, field types, definition presence
service Method presence, argument types & order, return types, modifiers
enum / flags Member names, member numeric values
union Case order (discriminator index), case field types

Workflow

1. Initialize the lock

ionc lock init

Creates ion.lock.json from the current schema. Run this once after the initial schema is stable.

2. Validate on every compile

ionc compile

The compiler automatically validates against the lock file. Breaking changes are reported as errors (ION0020–ION0029).

3. Intentional breaking changes

ionc compile --update-lock

When you intentionally make a breaking change, pass --update-lock to regenerate the lock file. This is a deliberate acknowledgment.

4. Check only

ionc lock check

Validates the current schema against the lock without running code generation.

Breaking Change Detection

The following modifications are detected as breaking:

Change Code Severity
Field removedION0020Error
Field reorderedION0021Error
Field type changedION0022Error
Definition removedION0023Error
Definition kind changedION0024Error
Method removedION0025Warning
Method signature changedION0026Error
Enum/flags value changedION0027Error
Union case reorderedION0028Error
Non-nullable field addedION0029Warning

Safe Changes

These changes are always safe and do not trigger warnings:

  • Adding new nullable fields to the end of a message
  • Adding new methods to a service
  • Adding new members to an enum or flags (at the end)
  • Adding new union cases (at the end)
  • Adding entirely new types/services/definitions

CI/CD Integration

In CI pipelines, use lock validation to catch breaking changes before merge:

# GitHub Actions example
- name: Validate schema
  run: ionc lock check --json
  continue-on-error: false