Skip to content

Encoding Profiles

Twilic v2 defines four encoding profiles. Each profile trades off flexibility, wire size, and session requirements differently. Pick the profile that matches your transport and data shape — not the other way around.

Profile overview

ProfileSchema requiredSession requiredBest for
DynamicNoNoAd-hoc values, single objects, first adoption
BatchNoNoSame-shape record lists, API pages, cache snapshots
BoundYesNoFixed message types, payment events, max density
StatefulNoYesWebSocket ticks, incremental entity sync

All profiles produce v2-conforming bytes decodable by any v2 SDK.

Dynamic Profile

The default. Encode any TwilicValue tree without prior agreement on shape.

ts
import { encode, decode } from "@twilic/core";
const bytes = encode({ id: 1n, name: "alice" });

Wire behavior:

  • First occurrence of each shape sends field names
  • Repeated strings within a message are interned
  • Homogeneous numeric arrays may auto-select typed vector codecs
  • No cross-message state

Use when: single HTTP bodies, one-off cache entries, prototyping.

Batch Profile

Encodes multiple same-shape records as one message with shared shape definition.

ts
import { encodeBatch } from "@twilic/core/advanced";
const bytes = encodeBatch(records);

Wire behavior:

  • Field names sent once per batch
  • String interning across all records
  • Row batch (row_batch) or columnar batch (col_batch) selected by encoder

Size vs MessagePack (same-shape records):

RecordsApprox. size vs MessagePack
1060–70%
10030–40%
1,00020–30%

Use when: list API responses, telemetry flushes, bulk cache warm-up.

See Batch & Columnar.

Bound Profile

Schema-aware encoding. Field names omitted; positions and types come from a Schema.

ts
import { encodeWithSchema } from "@twilic/core/advanced";
const bytes = encodeWithSchema(schema, value);

Wire behavior:

  • Field names not sent
  • Enum fields encode as bit indices
  • Range constraints enable bitpacking
  • Comparable to Protobuf density on single records

Use when: payment messages, fixed RPC contracts, hot paths with stable structure.

See Schema-Bound Encoding.

Stateful Profile

Maintains encoder/decoder state across an ordered message sequence.

ts
import { createSessionEncoder } from "@twilic/core";
const enc = createSessionEncoder();
enc.encode(fullValue); // baseline
enc.encodePatch(updated); // changed fields only
enc.reset(); // after disconnect

Wire behavior:

  • State patches reference previous message or base snapshot
  • Trained dictionaries accumulate across session
  • Template batches reuse column templates

Use when: WebSocket dashboards, game state sync, live metrics.

Not for HTTP Stateful profile requires ordered delivery and persistent session state. Do not use on stateless HTTP request/response. :::

See Stateful Streams.

Decision flowchart

Profile progression

Typical adoption path:

text
1. Dynamic everywhere (drop-in MessagePack replacement)
2. Batch on list/bulk endpoints
3. Stateful on WebSocket products
4. Bound on 2–3 latency-critical fixed messages

SDK entrypoints by profile

ProfileJavaScriptRustPythonGo
Dynamicencode()encode()encode()Encode()
BatchencodeBatch()encode_batch()encode_batch()EncodeBatch()
BoundencodeWithSchema()encode_with_schema()encode_with_schema()via SessionEncoder
StatefulcreateSessionEncoder()create_session_encoder()create_session_encoder()NewSessionEncoder()

Released under the CC-BY-4.0 License.