flatbufferscapnprotozero-copyserializationperformanceformats

FlatBuffers & Cap'n Proto: Zero-Copy Serialization Beyond JSON

·8 min read·Performance

The step even Protobuf can't skip

JSON has to be parsed from text. Protobuf and the binary formats are far more compact, but they still have a deserialization step: reading the wire bytes and building in-memory objects before you can touch a field. For most apps that's fine. But in games, high-frequency trading, and IPC where you read millions of messages a second — or a huge file you want to mmap and touch a few fields of — that unpack step is the bottleneck. FlatBuffers and Cap'n Proto remove it entirely with zero-copy access.

What "zero-copy" actually means

The trick is that the serialized layout is already the in-memory layout. Instead of parsing bytes into a new object graph, these formats lay data out so that a field lives at a known offset, and you read it directly from the raw buffer:

text
Protobuf:   [ wire bytes ] ──parse──▶ [ in-memory objects ] ──▶ read field
FlatBuffers:[ buffer ] ─────────────────────────────────────▶ read field @ offset
                        (no parse, no allocation)

You receive a buffer over the network or mmap it from disk, and accessing monster.hp just follows an offset into those exact bytes. There is no decode, no allocation, no object construction — which is why Cap'n Proto's tagline is "infinity times faster" than parsing: the parse step is zero work because there is no parse step.

FlatBuffers vs Cap'n Proto

Both are zero-copy and schema-driven (you define types in an IDL and generate accessors), with a similar niche:

  • FlatBuffers — from Google, born for game development and mobile. Extremely mature, tiny runtime, broad language support. You access data through generated accessor methods that read directly from the buffer. Optional verification checks a buffer is well-formed before you trust it.
  • Cap'n Proto — by a Protobuf co-author, designed as "Protobuf done for zero-copy." Same zero-copy core plus a built-in RPC system with *promise pipelining* (chaining dependent calls without extra round-trips). Slightly richer feature set aimed at inter-service communication.

Both trade some size and flexibility for that read speed: the buffers are larger than tightly-packed Protobuf (fields are aligned to fixed offsets), and the rigid layout is less forgiving to hand-edit.

The trade-offs — and why JSON usually still wins

Zero-copy is a specialist tool, not a default. Weigh it honestly:

  • You need a schema and codegen. Like Protobuf, there's no self-describing, human-readable payload — you can't just curl it and read it.
  • Bigger than Protobuf on the wire. Fixed offsets and alignment cost bytes; if you're bandwidth-bound rather than CPU-bound, Protobuf may serialize smaller.
  • Rigid and low-level. The ergonomics are more awkward than JSON or even Protobuf — you work through generated accessors, not plain objects.
  • Overkill for most apps. If you're not reading millions of messages per second or memory-mapping large files, the parse step you're eliminating wasn't your bottleneck.

For nearly every web API, config file, and inter-service message, JSON remains the right choice for its universality and readability, and Protobuf covers most cases where you've outgrown JSON's size and speed. Zero-copy formats earn their place only at the extreme end.

When to reach for zero-copy

  • Game engines — deserializing entity and asset data every frame; FlatBuffers is a staple here.
  • Ultra-low-latency systems — trading, real-time telemetry, anything counting microseconds per message.
  • Memory-mapped large files — touch a few fields of a huge dataset without loading or parsing the whole thing.
  • High-throughput IPC / RPC — millions of small messages between processes (Cap'n Proto's RPC shines).

The decision ladder is: JSON for interoperability → **Protobuf** when size and speed matter → FlatBuffers/Cap'n Proto when even the deserialization step is too expensive. For the analytics-shaped version of "compute without parsing," see Apache Arrow vs JSON. To measure whether you actually have a payload problem first, check your JSON size.

Frequently asked questions

It's a serialization approach where the on-the-wire byte layout is identical to the in-memory layout, so you read fields directly from the raw buffer at known offsets with no parsing, decoding, or object allocation. FlatBuffers and Cap'n Proto are the main examples.

Protobuf must deserialize its compact wire format into in-memory objects before you can access fields. FlatBuffers skips that entirely — you read fields straight from the buffer. FlatBuffers is faster to access and needs no allocation, but its buffers are larger than Protobuf's tightly packed encoding.

Both are zero-copy, schema-driven formats. FlatBuffers, from Google, targets games and mobile with a tiny runtime. Cap'n Proto, from a Protobuf co-author, adds a built-in RPC system with promise pipelining and is aimed more at inter-service communication.

Only at the performance extreme: game engines deserializing every frame, ultra-low-latency systems, memory-mapped large files, or very high-throughput IPC. For typical web APIs and config, JSON's readability wins; for most cases where you've outgrown JSON, Protobuf is enough.

They require a schema and code generation, produce non-human-readable payloads, are larger on the wire than Protobuf, and have more rigid, low-level ergonomics. They only pay off when eliminating the deserialization step addresses a real bottleneck.

Try JSONKit — JSON Developer Tools

Format, validate, convert and diff JSON. Instant, accurate and 100% private.