vs MessagePack, CBOR
MessagePack and CBOR are self-describing: a decoder can read a payload without its schema. That is often the right tradeoff, but their plain formats use about 3× as many bytes in these fixtures.
| Codec | Person | Nested event | 100 events |
|---|---|---|---|
| shorn | 8 | 43 | 4,135 |
| msgpackr shared records | 10 | 52 | 4,993 |
| cbor-x shared records | 14 | 62 | 5,972 |
| @msgpack/msgpack | 23 | 115 | 11,281 |
| msgpackr plain | 25 | 121 | 11,881 |
| cbor-x plain | 26 | 122 | 11,972 |
shorn is 64% smaller than plain msgpackr for the nested event and 65% smaller for the batch. It is 17% smaller than msgpackr shared records, whose reported steady-state sizes exclude their structure table.
How record modes compare
Section titled “How record modes compare”msgpackr shared records and cbor-x record extensions also move field names out of each payload. The difference is how that shared structure is defined and distributed.
| shorn | Shared records | |
|---|---|---|
| Where key names live | your validation schema | a structure table both ends synchronize |
| How it reaches the reader | you already deployed the schema | out-of-band state, built as records are seen |
| On a mismatch | DecodeError with fingerprinted() | depends on table state |
| Sizes quoted | standalone | steady-state, table excluded |
Both approaches require shared structure outside the payload. With shorn, that structure is the validation schema you already deploy.
Speed: shorn now leads both directions
Section titled “Speed: shorn now leads both directions”| Fixture | Op | shorn | msgpackr records |
|---|---|---|---|
| Person | enc | 25.16M | 10.55M |
| Person | dec | 67.55M | 18.96M |
| Nested event | dec | 11.45M | 8.36M |
| 100 events | dec | 116.3K | 88.1K |
shorn leads every fixture in both directions, including Unicode-heavy decoding (7.68M vs 3.97M). The nested event and batch used to be shorn’s largest performance gap — shared-record decoders were roughly 2× faster there. Generating a record decoder per object schema closed that gap and reversed it: shorn is now 1.37× faster on the nested event and 1.32× on the batch. See Throughput.
msgpackr records still encode text-heavy payloads faster, but only barely (8.04M vs shorn’s 7.74M on the Unicode fixture) — the one fixture in either direction where shorn does not lead this table.
Brotli reverses the size result
Section titled “Brotli reverses the size result”100,000 repetitive events:
| Codec | Raw | Gzip | Brotli q6 |
|---|---|---|---|
| shorn | 4,231,777 | 924,494 | 603,189 |
| msgpackr records | 4,995,339 | 1,114,738 | 513,630 |
shorn is smaller raw and under gzip, but 17% larger under Brotli. Brotli’s larger window compresses repeated metadata particularly well. If you store repetitive Brotli-compressed data, benchmark your own payloads. For the high-entropy fixture, shorn ranks first raw and under gzip, and second under Brotli.
Bundle size
Section titled “Bundle size”| Codec | Minified | Gzip |
|---|---|---|
| shorn | 17.57 KB | 5.39 KB |
| @msgpack/msgpack | 21.20 KB | 5.93 KB |
| msgpackr | 27.59 KB | 10.39 KB |
| cbor-x | 29.10 KB | 10.82 KB |
Validation libraries are excluded from every row, and shorn assumes your application already ships one. msgpackr records also start much faster: 1.00 µs compared with shorn’s 52–66 µs.
What they keep
Section titled “What they keep”- No schema needed to read. A generic tool can inspect any payload.
- Broad value support. cbor-x handles
Date,Map,Set,bigintnatively; shorn refuses all four (rich types). - Cross-language. Both are standards with implementations everywhere; CBOR is an IETF standard.
- Streaming. Both support incremental encode and decode.
- Encode speed on text. msgpackr records still encode the Unicode fixture faster.
- Startup. msgpackr records are ready in 1.00 µs against shorn’s 52–66 µs.
Choosing
Section titled “Choosing”| Use | When |
|---|---|
| shorn | TypeScript both ends, already validating, smallest raw and gzip payloads matter |
| msgpackr | You need Date/Map/Set natively, cold-start latency dominates, or you cannot guarantee a schema on both ends |
| @msgpack/msgpack | Conservative standard MessagePack with broad interop |
| cbor-x | You need CBOR specifically, usually for standards compliance |
The main question is whether both endpoints have the schema. If they do, shorn can omit repeated structure from the payload. If they do not, use a self-describing format such as MessagePack.