Skip to content

Migrating from MessagePack

If your team already ships MessagePack on internal boundaries, you have done the hard organizational work: stakeholders accept binary payloads, SDKs are integrated, and operational playbooks exist. Twilic migration is an incremental compression upgrade, not a greenfield format change.

This guide covers when the switch is worth it, how to run a safe parallel rollout, and what to watch for in production.

Should You Migrate?

Migrate when MessagePack is working but plateaued — especially if benchmarks show key repetition dominates your payloads.

SignalMigrate?
Bulk/list payloads with same object shapeYes — Twilic Batch shines
Long-lived streams with mostly stable fieldsYes — Stateful patches
Columnar telemetry batchesYescol_batch
Single one-off maps, no batchingMaybe not — gains are small
Embedded/constrained env with tiny MessagePack libEvaluate SDK size first
Public API on MessagePackUnlikely — prefer JSON or Protobuf for externals

Run a benchmark on production-shaped data before committing:

bash
git clone https://github.com/twilic/examples.git
cd examples
pnpm install
# Pick the closest example:
pnpm example:api-response # list APIs
pnpm example:telemetry # event batches
pnpm example:websocket:simulate # streaming patches
pnpm example:cache-payload # cache objects

See also the Benchmark page for throughput numbers.

What Stays the Same

Twilic Dynamic mode shares MessagePack's mental model:

  • Self-describing values: null, bool, int, float, string, binary, array, map
  • No schema required for first adoption
  • Polyglot SDKs — encode in one language, decode in another
  • Binary wire format (not human-readable)

Your application logic — domain objects, REST routes, cache keys — does not need to change shape.

What Gets Better

MessagePack limitationTwilic capability
Field names in every mapShape + key interning per message
Repeated strings in batchesString interning
Homogeneous numeric arrays as tagged valuesTyped vectors + delta/XOR/RLE codecs
Full object every stream tickStateful field patches
No columnar modecol_batch for telemetry

Parallel Rollout Playbook

Borrow the pattern used in large-scale MessagePack cache migrations (e.g. six-month parallel encode with fallback):

Phase 1 — Encode comparison (1–2 weeks)

  • Sample production payloads (anonymized)
  • Encode with MessagePack and Twilic side by side
  • Record size ratio at realistic batch sizes
  • Share results with service owners

Phase 2 — Dual decode (2–4 weeks)

  • Deploy decoders that accept both formats
  • Use a version byte or Content-Type to distinguish:
text
0x01 → legacy MessagePack
0x02 → Twilic v2 Dynamic
  • Producers stay on MessagePack; validate decode path only

Phase 3 — Canary encode (2–4 weeks)

  • One low-risk producer switches to Twilic (read-heavy internal API or forwarder tier)
  • Monitor error rates, latency, consumer lag
  • Keep instant rollback to MessagePack encode

Phase 4 — Expand + enable Batch/Stateful

  • Roll encode forward service by service
  • Enable encodeBatch where responses are lists
  • Enable SessionEncoder on WebSocket routes after client updates ship

Phase 5 — Retire MessagePack

  • Remove dual-decode after all producers migrate
  • Document the format in your internal platform standards

Compatibility Checklist

ItemAction
Map key typePrefer string keys for cross-language stability
Extension typesMap MessagePack ext types to Twilic extensions or embed as bin during transition
Timestamp encodingAlign on Twilic timestamp representation in Bound/Dynamic docs
Max payload sizeSet decode limits in every SDK
Untrusted inputNever typeless-decode; allowlist expected shapes at boundaries
Golden testsStore byte fixtures for both formats during dual period

Key and Schema Strategy

MessagePack teams often debate int keys vs string keys. Twilic follows the same discipline:

  • String keys — best for versioning, cross-team contracts, JSON interop
  • Int keys / array maps — acceptable in closed hot paths with codegen
  • Version byte prefix — recommended for cache and queue payloads

Document your choice in an internal RFC before wide rollout.

Debugging During Migration

Binary migration pain is invisible payloads. Mitigate upfront:

  • Sampled JSON sidecars in staging (never log full production PII)
  • Hex dump tools in your internal CLI
  • Twilic Playground for reproducing fixtures — Playground
  • Size metrics per endpoint: msgpack_bytes vs twilic_bytes histogram

Rollback Plan

Keep MessagePack encode for one release behind a feature flag:

ts
const bytes = featureFlags.twilicEncode
? twilic.encodeBatch(records)
: msgpack.encode(records);

Rollback is flipping the flag — no data migration required if dual-decode was deployed.

When Not to Migrate

Stay on MessagePack if:

  • Payloads are already small enough for your SLOs and budget
  • You depend on a minimal C/embedded MessagePack implementation with no Twilic port
  • Your bottleneck is business logic, not serialization

Twilic is an optimization, not a mandate.

Next Steps

Released under the CC-BY-4.0 License.