---
url: /spec/v1.md
---
# v1 Legacy Reference Profile

The v1 reference profile is preserved for historical reference and existing v1 payloads. The current specification family is [Twilic v3](/spec/v3).

v2 is a **clean break** from v1. A v2 decoder is not required to decode v1 payloads.

## Key Differences from v2

| Aspect | v1 | v2 |
| --- | --- | --- |
| Wire model | Top-level message-kind envelope byte | Tag-table model, no envelope byte |
| Key interning | Session-scoped | Message-local, resets per message |
| Shape interning | Implicit / control-message driven | Explicit `shape_def` / `shape_ref` tags |
| String interning | Session-scoped | Message-local |
| Batch | Via control messages | Explicit `row_batch` / `col_batch` tags |
| Stateful forms | Integrated into control flow | Optional separate profile |

## Why v2?

v1's session-scoped intern tables made stateless operation awkward — every message required session context to decode. v2 moves interning to message-local scope, making stateless one-shot messages fully self-sufficient while preserving session-level optimization as an optional layer.

v2's tag-table model is also more compact for one-shot values: there is no top-level envelope byte overhead.

## Migration

If you are maintaining a v1 implementation, follow the [v1 → v2 Migration Runbook](/guide/migration-v1-to-v2).

Summary of code changes:

1. Per-message intern tables: all `key_id`, `str_id`, `shape_id` assignments must reset at each top-level message boundary.
2. Replace control-message-driven shape registration with explicit `shape_def` / `shape_ref` tags (`0xD6` / `0xD7`).
3. Replace implicit batch encoding with explicit `row_batch` (`0xDB`) and `col_batch` (`0xDC`) tags.
4. Stateful forms (`state_patch`, `template_batch`) remain optional — they can be introduced incrementally.

For the full v1 specification, see the [`versions/v1.md`](https://github.com/twilic/twilic/blob/main/versions/v1.md) file in the twilic repository.
