Skip to content
Quasar Tools Logo

MessagePack vs JSON: Size, Speed and Overhead

MessagePack vs JSON compared: binary encoding size savings of 20–50%, serialisation speed, type handling, and when to switch — with a free browser-based size comparison tool.

DH
12 min read2,750 words

JSON is the lingua franca of web APIs — readable, universal, and supported everywhere. MessagePack is a binary serialisation format designed to carry the same data in 20–50% fewer bytes, with faster parsing on both ends. Understanding exactly where that size reduction comes from, what you give up, and when the trade-off is worth making is the difference between a premature optimisation and a measurable infrastructure improvement.

20–50%Smaller than minified JSONTypical payload savings
2–4×Faster serialisationvs text JSON parsing
< 1sSize comparison timeFor any JSON payload

What is MessagePack?

MessagePack is a binary serialisation format created by Sadayuki Furuhashi in 2008 and published as an open specification. It encodes the same data types as JSON — null, boolean, integer, float, string, array, map — but uses compact binary representations instead of human-readable text. A boolean `true` that takes 4 bytes as JSON text occupies exactly 1 byte in MessagePack. A small integer like 42 takes 3 bytes in JSON and 1 byte in MessagePack.

The format is schema-free: like JSON, it does not require a pre-defined schema to encode or decode data. This makes it a drop-in replacement for JSON in most API contexts — you swap the serialiser without changing the data model. MessagePack is widely supported with official and community libraries in Python, JavaScript, Go, Ruby, Java, C++, Rust, and over 50 other languages.

How MessagePack encoding works

  • Type tag byte — every value starts with a 1-byte tag that encodes the type and, for small values, the value itself (fixint, fixstr, fixarray, fixmap).
  • Integers — small integers (0–127) are 1 byte total. Larger integers use 2, 4, or 8 bytes depending on their magnitude, always smaller than their decimal text representation.
  • Strings — encoded as a length-prefixed UTF-8 byte sequence. Short strings (≤31 chars) use a 1-byte header; longer strings use a 2 or 4-byte header.
  • Booleans and null — each encode as exactly 1 byte. In JSON, `true` is 4 bytes, `false` is 5 bytes, `null` is 4 bytes.
  • Arrays and maps — length-prefixed; small arrays (≤15 elements) use 1 byte of overhead versus JSON's `[` `]` brackets plus commas.

Note

MessagePack is not a compression algorithm — it does not apply LZ77, Huffman coding, or any form of entropy compression. The size reduction comes entirely from using compact binary type encodings instead of text characters. Applying gzip or Brotli compression on top of MessagePack adds further reduction, but text-compressed JSON often closes the gap significantly because JSON's repetitive key names compress extremely well.

Size comparison: how much smaller is MessagePack?

The size reduction from switching to MessagePack depends entirely on your payload's data composition. Payloads with many numeric fields, booleans, and null values see the largest gains. String-heavy payloads — long text values, UUIDs, ISO date strings — see smaller gains because the string content itself is stored as raw UTF-8 bytes in both formats.

The savings come from type information and structural overhead, not from compressing the data values themselves. A 200-character string costs roughly the same in both formats.

MessagePack specification rationale

Size comparison by data type

ValueJSON bytes (minified)MessagePack bytesSaving
true4175%
false5180%
null4175%
42 (integer)2150%
1000 (integer)4250%
"hello"7614%
"2026-06-11"12118%

Real-world payload benchmarks

A typical REST API response with mixed data types — IDs, names, timestamps, status flags, and counts — sees 20–35% size reduction. A payload of pure numeric data (sensor readings, analytics events) can achieve 40–50% reduction. A payload of mostly long string values (article bodies, log messages) may see only 5–15% reduction. The JSON vs MessagePack Size Comparison tool on Quasar Tools measures the exact byte savings for any specific JSON payload — paste your production payload and read the actual percentage in under a second.

Tip

Before deciding to adopt MessagePack, measure the size savings on your actual production payloads, not synthetic benchmarks. Payloads with long repeated key names — common in verbose API designs — compress extremely well with gzip. Sometimes gzip-compressed JSON is smaller than uncompressed MessagePack. Always compare gzip+JSON against gzip+MessagePack for a fair evaluation.

JSON vs MessagePack Size Comparison

Paste any JSON payload and see its MessagePack byte size, exact percentage savings, type-by-type breakdown, and hex preview — browser-local, no upload.

Open tool

Serialisation speed: how much faster is MessagePack?

MessagePack serialisation and deserialisation is typically 2–4x faster than standard JSON text processing in benchmarks. The speed advantage comes from skipping UTF-8 tokenisation: JSON parsers must scan every byte looking for structural characters (braces, quotes, commas, colons), while MessagePack parsers read a type tag and jump directly to the next value boundary. No quote scanning, no escape handling, no number-string-to-integer conversion.

Language-specific performance context

The speed gap varies significantly by language runtime. In Python, `msgpack` is 3–5x faster than the standard `json` module for typical payloads. However, `orjson` (a Rust-backed Python JSON library) is nearly as fast as `msgpack` for many workloads — the gap narrows to 1.2–1.5x. In Node.js, `@msgpack/msgpack` outperforms built-in `JSON.parse` by roughly 2x. In Go, the performance gap is smaller still because Go's standard `encoding/json` is already quite fast.

Where speed matters most

The serialisation speed benefit is most meaningful in high-throughput internal microservice communication where services exchange thousands of messages per second and serialisation is a measurable CPU cost. For a standard web API serving a few hundred requests per second, the difference between JSON and MessagePack serialisation time is negligible compared to database query time or network round-trip latency. Profile your actual bottleneck before optimising serialisation.

Note

In many production systems, the dominant cost is not serialisation time but payload transmission time. Switching from uncompressed JSON to MessagePack reduces transmission time proportionally to the size reduction. Enabling HTTP/2 and gzip compression on your existing JSON API often delivers similar or greater throughput improvements with zero code changes.

Type system differences between MessagePack and JSON

MessagePack and JSON share the same core type set — null, boolean, number, string, array, and object/map — but MessagePack is richer at the numeric and binary levels. These differences matter when you are migrating an existing JSON API or designing a new protocol, because some MessagePack types have no direct JSON equivalent.

Types MessagePack adds beyond JSON

  • Unsigned 64-bit integer — JSON has no integer type at all (numbers are IEEE 754 doubles, which lose precision beyond 2^53). MessagePack encodes uint64 values precisely.
  • Binary byte array — MessagePack has a native bin type for raw byte sequences. JSON has no equivalent — binary data must be base64-encoded as a string, adding ~33% size overhead.
  • Extension types — a reserved mechanism for application-specific types like timestamps (ext type 1), decimals, and custom tagged data. Enables semantic enrichment without schema.
  • Float32 — MessagePack can encode 32-bit floats (4 bytes). JSON always uses 64-bit double precision text representation, which is both larger and loses the f32 type information.

The type round-trip problem

A critical gotcha when migrating from JSON to MessagePack: JSON has only one number type (IEEE 754 double), while MessagePack distinguishes int8, int16, int32, int64, uint8–uint64, float32, and float64. If your application serialises a JSON number and deserialises it as MessagePack, the type may change. A value like 42 serialised from JavaScript (as a double) may deserialise in a strongly-typed language as a uint8. Always verify round-trip behaviour between your serialisation library and the consuming service.

FeatureJSONMessagePack
Human-readable✓ Yes✗ Binary only
Integer types✗ None (double)✓ int8–int64, uint8–uint64
Binary data✗ Base64 needed✓ Native bin type
64-bit integers✗ Precision loss✓ Full uint64/int64
Schema required✗ Schema-free✗ Schema-free
Browser native✓ JSON.parse/stringify✗ Library required
Streaming support✓ Yes✓ Yes (with libraries)
Extension types✗ No✓ Yes (ext type)

MessagePack timestamps

MessagePack's extension type 1 is a standardised timestamp format that encodes Unix time as a 4, 8, or 12-byte binary value with nanosecond precision. This is smaller and more precise than an ISO 8601 string like `"2026-06-11T14:30:00Z"` (20 bytes as JSON) and avoids timezone ambiguity. Most MessagePack libraries automatically encode and decode this extension type, making timestamp handling transparent for the application layer.

When to use MessagePack vs JSON

The choice between MessagePack and JSON is not about which format is "better" — it is about which constraints matter in a given context. JSON wins on universality, tooling, and debuggability. MessagePack wins on payload size and parsing speed. Most APIs should start with JSON and migrate to MessagePack only after profiling confirms that serialisation or payload size is a genuine bottleneck.

Use MessagePack when

  • Internal microservice communication — services you control on both ends, where human-readability is not required and throughput is a measurable concern.
  • High-frequency message brokers — Kafka, NATS, RabbitMQ topics carrying thousands of events per second where payload size directly impacts throughput and storage costs.
  • Mobile APIs with constrained bandwidth — reducing payload size by 30% on a high-traffic mobile API meaningfully reduces data usage and latency on cellular connections.
  • Real-time gaming or IoT protocols — where binary frames, sub-millisecond latency, and bandwidth efficiency are design requirements from the start.
  • Binary data transport — payloads containing raw bytes (images, audio chunks, cryptographic material) avoid the 33% base64 overhead of JSON encoding.

Stay with JSON when

  • Public APIs — external consumers expect JSON; adding MessagePack requires client-side library adoption and content negotiation middleware.
  • Developer-facing tooling — browser DevTools, curl, Postman, and API explorers all work natively with JSON; debugging MessagePack requires extra decode steps.
  • Low-traffic endpoints — the engineering cost of adding MessagePack support far outweighs the benefit when payload volume is small.
  • Already using gzip compression — HTTP gzip or Brotli compresses JSON repetitive key names aggressively, often achieving similar payload reduction to raw MessagePack.

Warning

Content negotiation is the recommended migration path for existing JSON APIs: the server accepts both Accept: application/json and Accept: application/msgpack, and responds in the format the client requests. This allows gradual adoption without breaking existing clients. Do not flip an existing public API exclusively to MessagePack — the debuggability and tooling cost to external consumers is rarely worth the size saving.

Integration and tooling

MessagePack has mature library support across all major languages, but it is not natively supported in browsers or standard HTTP frameworks the way JSON is. Adding MessagePack to an existing stack means adding a dependency, updating content-type handling, and updating any debugging or logging tooling that consumes raw request/response bodies.

Library support by language

  • Python — `msgpack` (PyPI). Fast C extension with pure-Python fallback. Drop-in replacement for `json` in most use cases.
  • JavaScript / Node.js — `@msgpack/msgpack` (npm). TypeScript-native, supports streaming. Also `msgpackr` for higher performance.
  • Go — `github.com/vmihailenco/msgpack` or `github.com/ugorji/go/codec`. Both implement the full spec with extension type support.
  • Java / JVM — `msgpack-java` (official). Integrates with Jackson via `jackson-dataformat-msgpack` for drop-in JSON replacement.
  • Rust — `rmp` and `rmp-serde`. Serde-based serialisation means adding MessagePack support alongside existing JSON is a one-line change.

Validating your payload before encoding

Before switching a production API to MessagePack, validate the JSON structure you are encoding. A JSON payload with structural errors — trailing commas, unquoted keys, unexpected nulls — will silently produce a malformed MessagePack output that causes cryptic decode errors on the consumer side. Run your payload through the JSON Formatter Viewer to check structure and the JSON Schema Validator to verify it conforms to your expected shape before encoding.

JSON Compressors

Explore JSON payload reduction options — MessagePack comparison, key shortening, and minification — all browser-local with no upload required.

Open tool

Trade-offs and caveats

MessagePack is not a free upgrade from JSON. The binary format introduces real costs in debuggability, tooling compatibility, and developer onboarding. These are not hypothetical concerns — they are the primary reason most teams that evaluate MessagePack ultimately keep JSON for everything except the specific high-volume, internal channels where the trade-off clearly pays off.

Debuggability is the biggest practical cost

With JSON, you can read a raw request body in your terminal, browser DevTools, or any text log. With MessagePack, you see binary output like `\x81\xa4name\xa5Alice`. Every debug session requires a decode step. Teams using MessagePack in production typically add a dedicated decode utility to their internal tooling and log decoded payloads in their observability stack alongside the binary frames. The development friction is real — do not underestimate it.

Schema evolution and versioning

MessagePack is schema-free like JSON, so adding or removing fields does not break the format. However, the lack of schema means there is no built-in backward-compatibility mechanism beyond application-level field checking. For evolving APIs, MessagePack's extension types can carry schema version metadata, but this requires explicit design. For strictly typed, evolving protocols, Protobuf's field-number-based schema evolution is more robust — see the JSON Schema vs Protobuf comparison for the full trade-off analysis.

The gzip equaliser

HTTP gzip compression often closes the gap between JSON and MessagePack dramatically. JSON APIs with repetitive keys repeated across array elements compress extremely well because gzip exploits that repetition. A typical API response that is 40% smaller as raw MessagePack might only be 5–10% smaller after both formats are gzip-compressed. Always benchmark compressed MessagePack against compressed JSON before committing to a migration.

Warning

Never adopt MessagePack as a blanket API-wide change without profiling. Measure payload size and serialisation time on your actual production payloads using the [JSON vs MessagePack Size Comparison](/tools/compress/json-compressors/json-vs-messagepack) tool. Then measure the same payloads after gzip compression. Only proceed if the comparison shows a meaningful improvement worth the debuggability cost.

Key takeaways

  • MessagePack is 20–50% smaller than minified JSON on typical payloads — the exact saving depends on how many integers, booleans, and null values the payload contains.
  • Serialisation speed is 2–4x faster than text JSON in benchmarks, but high-performance JSON libraries like orjson (Python) and simdjson (C++) narrow this gap significantly.
  • MessagePack adds native types JSON lacks: unsigned 64-bit integers, raw binary data, float32, and extension types for timestamps and custom data.
  • The biggest practical trade-off is debuggability — MessagePack output is binary and cannot be read directly in DevTools, curl, or log output without a decode step.
  • Gzip-compressed JSON often closes the size gap with uncompressed MessagePack — always benchmark both under gzip before migrating.
  • The JSON vs MessagePack Size Comparison tool on Quasar Tools measures exact byte savings and type breakdown for any JSON payload in under a second.
  • Best use cases are internal high-throughput microservices, message brokers, mobile bandwidth-constrained APIs, and payloads containing raw binary data.

Frequently Asked Questions

MessagePack is typically 20–50% smaller than minified JSON. The exact savings depend on your payload shape. Payloads with many integers, booleans, and null values compress most aggressively — small integers (0–127) encode as 1 byte in MessagePack versus 1–3 bytes in JSON text. Payloads dominated by long strings see smaller gains because strings are stored as raw UTF-8 bytes in both formats. Use the JSON vs MessagePack Size Comparison tool on Quasar Tools to measure the exact savings for your specific payload.

MessagePack serialisation and deserialisation is typically 2–4x faster than JSON text processing in benchmarks, because binary parsing skips the character-by-character UTF-8 tokenisation that JSON requires. The actual speed advantage in production depends heavily on the language runtime and library — high-performance JSON parsers (simdjson in C++, orjson in Python) narrow the gap significantly. The performance benefit is most pronounced in high-throughput microservice APIs processing thousands of requests per second.

MessagePack supports all JSON-compatible types: null, boolean, integer (signed and unsigned up to 64-bit), float (32-bit and 64-bit), UTF-8 string, binary byte array, array, and map. It also supports an extension type mechanism for custom types like timestamps, decimals, and application-specific data. Unlike JSON, MessagePack distinguishes between strings and raw binary data at the type level — a feature JSON cannot express without base64 encoding.

Yes. The @msgpack/msgpack npm package provides a browser-compatible MessagePack encoder and decoder with full TypeScript support. However, MessagePack is a binary format and cannot be used with browser localStorage (which only stores strings), sent as a plain text body, or logged in human-readable form without a hex viewer. For browser-to-server communication, set the Content-Type header to application/msgpack and ensure both sides share the same library version for consistent encoding.

For very small payloads (under 20 bytes), MessagePack may be the same size as or slightly larger than minified JSON. This happens because MessagePack type tags add 1 byte per value, and for tiny payloads the type overhead outweighs the compactness of binary encoding. For a single-field payload like {"ok":true}, JSON is 10 bytes and MessagePack is also around 8–9 bytes — negligible difference. The size advantage grows significantly with payload complexity and size.

No. MessagePack is a binary format — the encoded output is not human-readable without a dedicated decoder or hex viewer. This is one of the primary trade-offs versus JSON. During development, debugging MessagePack payloads requires a tool that decodes the binary back to a readable representation. The JSON vs MessagePack Size Comparison tool on Quasar Tools shows the first 64 bytes of the MessagePack output as hex, which is useful for verifying encoding correctness without a full decode step.

Yes, but it requires explicit configuration on both the client and server. The client must set the Accept: application/msgpack and Content-Type: application/msgpack headers, and the server must handle both JSON and MessagePack content types for backwards compatibility. Most REST frameworks (Express, FastAPI, Spring) support custom content negotiation middleware. GraphQL and OpenAPI tooling generally assumes JSON — adding MessagePack support requires custom serialisers and is rarely worth the engineering cost unless payload size is a measured bottleneck.

All three are binary serialisation formats more compact than JSON. Protobuf (from Google) uses a schema definition to remove field names entirely, achieving 5–10x JSON compression — the highest density of the three, but requires maintaining .proto schema files. MessagePack is schema-free like JSON, making it a drop-in replacement with no schema overhead. CBOR (RFC 7049) is an IETF standard with more data types and better extensibility than MessagePack. For API migration from JSON with minimal friction, MessagePack is the easiest starting point.

ShareXLinkedIn

Related articles