Skip to content

Performance

Twilic performance depends on profile choice, batch size, backend (N-API vs WASM), and payload shape — not on the format alone. Benchmark your production data before optimizing.

Backend selection (JavaScript)

BackendEnvironmentThroughputLatency
N-APINode.js 24+HighestLowest
WASMBrowser, edge, DenoGoodHigher init cost
ts
const kind = await init({ prefer: "napi" }); // or "wasm"

WASM requires one-time module load. Amortize across many encode/decode calls.

Profile impact

ProfileEncode costWire sizeDecode cost
Dynamic singleLowBaselineLow
Batch 256Medium30–70% smallerMedium
BoundLow–mediumSmallest single recordLow
Stateful patchLow70–90% smaller per tickLow

Highest ROI: Batch on repeated structure, Stateful on stable streams.

Batch size sweet spots

Measure on your hardware and payload:

bash
git clone https://github.com/twilic/benchmark.git
cd benchmark
pnpm install
pnpm bench
WorkloadStarting batch size
API list response50 (page size)
Telemetry flush256
Cache snapshot500–1000
WebSocket micro-batch4–16

Increase batch size until marginal size reduction per added record drops below your latency budget.

Transport-JSON fast path

For JavaScript, @twilic/core/advanced exposes transport-JSON encoding that skips some JS object traversal:

ts
import { encodeTransportJson, toTransportJson } from "@twilic/core/advanced";

const json = toTransportJson(value);
const bytes = encodeTransportJson(json);

Useful when values are already serialized or in high-throughput pipelines. See benchmark README.

N-API vs WASM benchmarks

Representative numbers from the Benchmark page (single 6-field object):

OperationTwilic (N-API)MessagePack
Encode~similarbaseline
Decode~similarbaseline

Gains come from wire size reduction (less I/O, less allocation) more than raw encode/decode microseconds on small objects.

Columnar telemetry

256-event batch (6 fields):

FormatSize
JSON~98 KB
MessagePack~65 KB
Twilic col_batch~8–12 KB

At 10,000 events/sec, that is the difference between ~650 MB/s and ~80 MB/s on the wire.

Rust / native SDKs

Rust, Go, and Python native implementations avoid JS/WASM overhead entirely. Use them on:

  • High-throughput agents and forwarders
  • Server-side batch encoding
  • Edge workers where N-API is unavailable (use WASM or native port)

Optimization checklist

  1. [ ] Benchmark production-shaped payloads (not toy JSON)
  2. [ ] Enable batch on list/bulk endpoints
  3. [ ] Tune batch size against latency SLO
  4. [ ] Use stateful patches on WebSocket products
  5. [ ] Promote hot paths to Bound profile when schema is stable
  6. [ ] Prefer N-API on Node.js servers
  7. [ ] Bundle WASM efficiently in browser (single init, reuse encoder)

Anti-patterns

PatternWhy it hurts
Batch size 1 on HTTP listsNo compression benefit
Stateful on HTTPSession overhead, no reuse
Re-encoding JSON → Twilic per fieldBatch at record level
Ignoring bigint in JSSilent precision loss, re-encode bugs

Released under the CC-BY-4.0 License.