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
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 removed | ION0020 | Error |
| Field reordered | ION0021 | Error |
| Field type changed | ION0022 | Error |
| Definition removed | ION0023 | Error |
| Definition kind changed | ION0024 | Error |
| Method removed | ION0025 | Warning |
| Method signature changed | ION0026 | Error |
| Enum/flags value changed | ION0027 | Error |
| Union case reordered | ION0028 | Error |
| Non-nullable field added | ION0029 | Warning |
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