Sota Misaki Projects

Twilic — Weaving Repeated JSON into One Wire

May 24, 2026
  • Rust
  • TypeScript
  • MessagePack
  • WebAssembly
  • N-API
github.com/twilic/twilic

Twilic is a documentation-first specification and multi-language implementation for a compact binary format aimed at structured data. The name comes from Old English twilic, the root of modern twill: repeated threads woven into one fabric—same idea for repeated object shapes, keys, and strings in a single wire representation.

I am building Twilic because JSON and MessagePack are easy for one-off objects, but the same schema sent hundreds of times still pays for field names and repeated strings on every row. Protobuf fixes that with a fixed schema; Twilic targets the middle ground—schema-less to start, then automatic interning and optional bound profiles when you know the shape.

What it does

Reference implementations live in twilic-rust, @twilic/core (N-API + WASM), twilic-go, and twilic-zig. Hono middleware is available for Content-Type-aware bodies.

Benchmark

Sizes below use the same fixtures as twilic/benchmark (local @twilic/core via N-API on Node 24). Throughput is in the same order of magnitude as MessagePack for encode/decode; the main win is wire size on repeated data.

PayloadTwilicMessagePackCBORBSONvs MessagePack
Single record140 B140 B144 B198 B0%
256 homogeneous records5,316 B19,505 B20,633 B28,241 B72.8% smaller
256 mixed records9,799 B20,893 B22,204 B32,956 B53.1% smaller
Session patch (first)89 B89 B93 B120 B0%

On a single small object, Twilic is designed not to be worse than MessagePack. On a 256-record homogeneous batch, encoded size drops to roughly one quarter of MessagePack in this harness—the case where key names and repeated strings dominate.

Reproduce locally:

git clone https://github.com/twilic/benchmark.git
cd benchmark
pnpm install
pnpm --dir ../twilic-js build
pnpm bench -- --twilic-vs-msgpack-only

Compare formats in the browser via the playground. A longer write-up (in Japanese) is on Zenn.

Good fit / poor fit

Good fit: telemetry or log batches, WebSocket events with stable shape, tabular columns (userId, active, country), edge-to-cloud links where bandwidth matters, teams already on MessagePack who only struggle with array batches.

Poor fit (explicit non-goals): replacing every JSON protocol, defining application semantics, or optimizing streams of tiny one-off payloads where MessagePack is already enough.