
Cap’n Proto
A binary format laid out like an in-memory struct, so reading needs no parse step, plus an RPC system built on object references and promise pipelining.
- What it is
- Remote procedure calls,File formats
- Type
- Open source
- Made by
- Cloudflare, Inc.
- License
- MIT
- Facts checked
- 6 October 2026
What it is
A Cap’n Proto message is arranged the way a compiler lays out a struct: fixed-width fields at fixed offsets, in 8-byte words, little-endian, with strings, lists and nested structs reached through relative pointers. The same bytes are the in-memory representation and the wire format, so there’s no encode or decode step. Generated accessors read fields straight from the buffer and check each pointer’s bounds before following it. You can memory-map a large file and read one field without paging in the rest, or share a message between processes. The price is size: unset fields and padding are written as zeros, so for the network there’s an optional packing step that squeezes zero bytes out. Schemas number fields @0, @1, … in the order they were added, and new fields go at the end of a struct, so old readers keep working.
The RPC system uses the same schemas. Interfaces have methods, and a reference to a remote object (a capability) is a field type: passing one to someone lets them call it, and nobody else can. Every call returns a promise at once, and you can call methods on that promise before the result arrives, so bar(foo()) goes out as two messages in one round trip. This promise pipelining comes from CapTP, the protocol of the E programming language. The reference implementation is in C++, together with the KJ async toolkit, and is maintained by the Cloudflare Workers team; Rust, Go, Python, C# and other implementations are separate community projects. It’s free under the MIT licence.
Why teams pick it
- No parse step: reading a field is a bounds check and a pointer hop, and big files can be memory-mapped and read lazily
- Promise pipelining collapses a chain of dependent calls into one network round trip, without merging methods into awkward combined ones
- Capability-based security: holding a reference is the permission to call it, which suits calls between parties that don’t trust each other
- Proven at scale inside Cloudflare Workers, between sandboxes and their supervisors, between machines and data centres, and for Durable Objects
- Small generated code, mostly inline accessors, which its author puts at an order of magnitude less than Protobuf’s per-type parsers
Watch out for
- Bigger messages than Protobuf unless you turn on packing, because unset fields and padding take space as zeros
- Arena allocation: a list can’t be resized once allocated, and objects discarded inside a long-lived message keep their space until the whole message is freed
- Only the C++ implementation is maintained by the core team; other languages vary in readiness and some lack RPC
- No built-in encryption (run it over TLS), and the FAQ says the RPC layer isn’t yet robust against resource-exhaustion attacks
- RPC objects are stateful, so calls to one object must reach the same machine and load balancing is left to you; the C++ implementation documents only level 1 of the protocol (no persistent capabilities or three-party handoff)
Alternatives
What all remote procedure calls have in common →
Apache ThriftOpen sourceFacebook’s 2007 RPC framework: define types and services in one IDL file, generate clients and servers for over 20 languages, and pick the wire protocol and transport separately.
gRPCOpen sourceGoogle’s open RPC framework: describe a service in a `.proto` file, generate typed clients and servers, and call them over HTTP/2 with streaming, deadlines and standard status codes.
Protocol BuffersOpen sourceGoogle’s schema-first binary encoding: messages defined in `.proto` files, fields identified by number, code generated for each language.How it fits with other technologies
What Cap’n Proto uses
What uses Cap’n Proto
Build a message and read it back with pycapnp · python
import capnp # pip install pycapnp
# Fields are numbered @0, @1, ... in the order they were added
with open("order.capnp", "w") as f:
f.write("""
@0xbf5147cbbecf40c1; # file ID, generated with `capnp id`
struct Order {
id @0 :UInt64;
customer @1 :Text;
itemIds @2 :List(UInt32);
}
""")
order_capnp = capnp.load("order.capnp")
msg = order_capnp.Order.new_message(id=150, customer="ada", itemIds=[1, 2, 3])
data = msg.to_bytes() # the in-memory layout, written out as is
print(len(data)) # 64: 8-byte words, fixed-width slots, pointers
# (to_bytes_packed() squeezes out the zeros: 22 bytes)
# No parse step: accessors read straight from the buffer, checking bounds
with order_capnp.Order.from_bytes(data) as order:
print(order.id, order.customer, list(order.itemIds)) # 150 ada [1, 2, 3]Cap’n Proto and Protocol Buffers#
Same author, opposite trade-off: Protobuf spends CPU to make messages small; Cap’n Proto spends bytes so that reading costs almost nothing.
| Cap’n Proto | Protocol Buffers | |
|---|---|---|
| Reading a message | Accessors read the buffer in place, after bounds checks | Parse the whole message into objects first |
| Read one field of a huge file | Yes: memory-map it and follow pointers | No: everything before the field must be parsed |
| Unset fields | Keep their slot, as zeros; packing removes them | Not written at all |
| Optional and required fields | Neither; use a union with Void or a sentinel default | optional with presence; required in proto2 and as a legacy Editions setting |
| RPC | Built in: capabilities and promise pipelining | Service definitions only; RPC comes from gRPC or others |
| Languages from the core team | C++ (others are community projects) | C++, C#, Java, Kotlin, Objective-C, PHP, Python, Ruby, Dart, Go |
| Licence | MIT | BSD 3-Clause |
Where it’s used#
Cloudflare Workers runtime
productionThe workerd runtime is built on Cap’n Proto and KJ. It carries messages between sandbox processes and their supervisors, between machines and data centres, and inside Durable Objects. Cloudflare’s logging pipeline used it before Varda joined.
Workers RPC
2024JavaScript-native calls between Workers and to Durable Objects, built on Cap’n Proto but with no schema to write. Functions and objects can be passed as arguments, and chained calls are pipelined into one round trip.
Cap’n Web
2025A schema-less sibling for browsers and the web stack, from the same author: the same object-capability model and pipelining, but the encoding is JSON.
Sandstorm
originThe self-hosted app platform Varda co-founded developed Cap’n Proto and used it heavily. The company stopped most operations in 2017 and dissolved in 2022; the open-source project continues.
See it in a real stack
No architecture uses Cap’n Proto yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2013–2025
Kenton Varda was the primary author of Protocol Buffers version 2, the one Google open-sourced. Cap’n Proto came out of years of working on Protobuf and listening to its users, and its big idea was to drop the encoding step altogether. On April 1, 2013 he announced it: “I may have rewritten Protocol Buffers. Again.” Because its encoding was also its in-memory format, a benchmark he admitted was unfair had it “infinity times faster”.
The project was developed at Sandstorm.io, the self-hosting start-up Varda co-founded, and used throughout its platform. Version 0.4, in December 2013, added the RPC system and promise pipelining, which he billed as “time-traveling RPC”. In March 2017 most of the Sandstorm team joined Cloudflare, which Varda called perhaps the biggest Cap’n Proto user.
At Cloudflare Varda leads Workers, whose runtime is built on Cap’n Proto. Version 1.0, in July 2023, was cut as a long-term-support release so the Workers team could make breaking C++ API changes on a new 2.0 branch. Workers RPC in 2024 and Cap’n Web in 2025 carried the object-capability model to JavaScript without schemas.
Why it’s built this way
- The wire format is the in-memory format
- Removing the parse step makes reading nearly free and allows memory-mapping and shared memory between processes. It requires arena allocation and fixed layouts, which is why lists can’t grow.
- Fields at fixed offsets, numbered in the order added
- With no per-field tags, compatibility comes from position: new fields are appended to a struct and old readers simply bounds-check, so nothing needs renumbering.
- Promise pipelining in the RPC protocol
- Over a high-latency link, a clean object interface turns one task into several round trips. Sending calls on not-yet-returned results keeps the clean interface and pays the latency once.
- Remote calls don’t pretend to be local
- Varda blames CORBA’s failure largely on making remote calls look like local ones. Cap’n Proto calls return promises and raise “disconnected” errors, so the network stays visible.
Timeline
- 2013
Announced on April 1; version 0.4 adds RPC in December
- 2017
The Sandstorm team, Varda included, joins Cloudflare in March
- 2022
Sandstorm the company formally dissolves; the project lives on
- 2023
Version 1.0 released in July as a long-term-support line
- 2024
Cloudflare launches Workers RPC, built on Cap’n Proto
- 2025
Cap’n Web brings the model to browsers, encoded as JSON
- Cap’n Proto news: Announcing Cap’n Proto (April 2013)
- Cap’n Proto: Introduction (Kenton Varda, primary author of Protocol Buffers v2)
- Cap’n Proto news: v0.4, time-traveling RPC (December 2013)
- Sandstorm blog: The Sandstorm team is joining Cloudflare (Kenton Varda, March 2017)
- Sandstorm: About (Kenton Varda, co-founder)
- Cap’n Proto: FAQ (Sandstorm and Cloudflare)
- Cap’n Proto: RPC protocol (promise pipelining, why CORBA failed)
- Cap’n Proto news: Cap’n Proto 1.0 (July 2023)
- Cloudflare blog: We’ve added JavaScript-native RPC to Cloudflare Workers (April 2024)
- Cloudflare blog: Cap’n Web, a new RPC system for browsers and web servers (September 2025)
Sources12 · facts checked 6 October 2026
- Cap’n Proto: Introduction (no encoding step, packing, generated code size)
- Cap’n Proto: Encoding spec (words, segments, pointers, packing)
- Cap’n Proto: Schema language (field numbering, evolving your protocol)
- Cap’n Proto: RPC protocol (capabilities, promise pipelining, levels, CapTP)
- Cap’n Proto: C++ RPC (level 1 implementation)
- Cap’n Proto: FAQ (optional and required fields, list resizing, security, stateful servers, Cloudflare)
- Cap’n Proto: Other languages
- Cap’n Proto news: Cap’n Proto, FlatBuffers and SBE compared (random access, arena allocation)
- Protocol Buffers docs: History (Protobuf is an interchange format, not tied to one RPC system)
- Protocol Buffers docs: Overview (languages supported by Google)
- capnproto/capnproto: LICENSE (MIT)
- pycapnp on GitHub (Python bindings)