# FastBinaryEncoding: a schema compiler for binary protocols

> Fast Binary Encoding is not a serialisation library but a toolchain. You describe a domain model once, and a generator produces native code for nine languages plus a compact binary format, so that a C++ service and a Python service can exchange the same structures without either side hand-writing a parser.

**chronoxor/FastBinaryEncoding** — Fast Binary Encoding is ultra fast and universal serialization solution for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift

- Repository: https://github.com/chronoxor/FastBinaryEncoding
- Website: https://chronoxor.github.io/FastBinaryEncoding
- Stars: 963 · Forks: 99
- Language: C++
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/chronoxor-fastbinaryencoding

## A generator, not a library you call

The framing in the readme is precise and it is the thing to understand first.

Fast Binary Encoding allows you to describe any domain models, business objects, complex data structures, and client and server requests and responses, and to generate native code for different programming languages and platforms.

So the unit of work is not a call, it is a schema. You write a model, and the toolchain produces a type in each target language, along with the code that reads and writes it. That is a compiler approach to the problem, and it is the right shape when a protocol is shared by services written in different languages, because the alternative is one hand-written codec per language per message, and those drift.

The workflow in the readme is six steps and it reads like a build pipeline. You create the domain model using base types, enums, flags and structs. You generate the domain model for any of the supported programming languages. You build the domain model library. You serialize and deserialize objects in the unified, fast and compact format. You convert objects to JSON so you can use them in a web API. And you implement the sender and receiver interfaces to create a communication protocol.

That last step is the one that makes it a protocol toolkit rather than a codec generator. The generated code is the data model, and the interfaces are where the transport goes, so the same model can be carried over HTTP, over a socket or over a message bus without regenerating anything.

## What the format covers

The feature list is a specification in miniature, and it is worth reading as a check against the types your own model needs.

The base types are the obvious ones: byte, bool, char, wchar, the signed integers from 8 to 64 bits, and float and double. The complex types add bytes, decimal, string, timestamp and uuid, and the collections cover array, vector, list, map and hash. On top of that there is support for nullable and optional types, enums, flags and structs.

The nullable and optional distinction is worth noting, because it is the kind of detail that decides whether a protocol round-trips faithfully. Both nullable and optional fields describe a value that may be absent, and the format supports them alongside enums, flags and structs.

There are three serialisation modes. The binary format is the compact one and the reason the project exists. The final serialisation is a variant of it, described separately in the readme's contents. And there is a JSON serialisation, whose stated purpose is to convert objects from the domain model in order to use them in a web API.

The JSON mode is what makes the toolchain usable in a modern service, and it is the pragmatic part of the design. A web API wants JSON, a device link wants compact bytes, and a system that supports both from one model is much nicer to maintain than one where the two representations are defined separately and drift.

## The benchmark table, and how much weight it carries

The readme leads with a comparison table against other protocols, and the numbers are interesting enough to look at carefully.

For the message in question, the comparison shows Cap'n Proto at 208 bytes with 558 nanoseconds to serialise and 359 to deserialise, Fast Binary Encoding at 234 bytes with 66 and 82, FlatBuffers at 280 bytes with 830 and 290, Protobuf at 120 bytes with 628 and 759, and JSON at 301 bytes with 740 and 500.

Two things stand out and they point in opposite directions. The serialisation time for this format is an order of magnitude better than the alternatives, which is what you would expect from a hand-rolled fixed layout format with no schema reflection at run time. The message size, however, is not the smallest, since Protobuf produces a smaller message for this case.

The honest caveat is that these are the project author's own numbers, and the readme points to a separate comparison repository for them, so they are reproducible in principle but they are not an independent evaluation. A benchmark of a serialisation library is also a benchmark of a particular message, on a particular machine, with a particular compiler and optimisation level, and the results move when any of those change.

The repository has a performance directory and the readme's contents list three separate benchmark sections, for serialisation, deserialisation and verification, which is the right structure for a library making performance claims. If the numbers matter to you, run them on your own data, because the difference between 66 and 558 nanoseconds is much larger than the difference between 234 and 208 bytes, and that is the trade the table is really making.

## Nine languages, one model

The language list is the other headline, and it is unusually wide for a schema generator.

There are generators for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby and Swift, and the repository carries a sample project for each of them alongside a set of C++ examples. The examples are worth looking at by name because they show the shape of a working integration: creating a model, printing it, printing it as JSON, sending and receiving, and the three serialisation variants, plain, final and JSON.

The supported platforms are Linux, macOS and Windows, and the build requirements are a C++ toolchain, CMake, git, a Python interpreter and a code generation tool. The continuous integration badges show how wide the build matrix is: Linux with both clang and gcc, macOS, and Windows under four separate toolchains, Cygwin, MSYS2, MinGW and Visual Studio.

Four Windows toolchains is unusual and it is a deliberate choice rather than an accident, because a protocol library used in embedded and industrial Windows software meets code built with all of those. Supporting them is work, and the badges are there to show it is still done on every commit.

## Struct keys, inheritance and versioning

The readme's contents list has three entries that point at the parts of a schema language that are hardest to get right, and they are worth a short section each.

Struct keys identify a struct on the wire by something more durable than its position in the model. If the fields are identified by name or by an explicit key, then you can add a field, or remove one, or reorder them, and an old peer and a new peer can still read each other's messages. If they are identified by position, none of that is possible.

Struct numeration is the associated mechanism for numbering structs, so that a message can say which struct it contains without a string lookup.

Struct inheritance lets one struct extend another, which is how a protocol expresses the fact that a particular request is a special case of a general one.

And then there is versioning, which the feature list describes as a versioning solution rather than as a version number. The distinction matters. A version number in a message header tells a reader that the format changed and it should give up. A versioning solution is about letting a reader understand an old message with a new reader, which is what a deployed fleet of devices actually needs.

The sender and receiver interfaces are the last piece. Once the model is generated for both ends, the transport is your code, and the interface is where you plug in yours. That is what lets the same generated model sit behind an HTTP endpoint, a TCP socket and a queue.

## The project state, and the one thing to check

The licence is MIT, the default branch is main, and the project is not archived, with the last push on 2026-10-13.

The release history is the thing to check. The newest tagged release in the list is 1.15.0.0 from July 2025, with the title fixed compilation errors, and before it 1.14.5.0 from November 2023, which fixed an issue with an undefined host lookup in the C++ generator, and 1.14.4.0 with minor build updates.

So the releases are infrequent, and there is more than a year between the newest tag and the last commit. The commit history is the more current record of what is happening, and the repository has a todo file for that.

Whether the infrequency is a problem depends on what you need. The format itself is documented in a specification document and a separate document for the format itself, and the readme links both, along with the documentation site and the downloads page. A wire format does not change often, and a generator that produces readable native code does not need to change often either.

The repository layout is consistent with that. There is a source directory, a headers directory, a modules directory, a bin directory for the tools, a documents directory for the specifications, a performance directory, a projects directory holding the per-language samples, a proto directory, a tests directory and an examples directory. There is also a generated code links file and a file with contributor instructions, and the project appears to be maintained with an AI assistant in the loop, which is consistent with the changelog entries about compilation errors in the generator.

## Conclusion

FastBinaryEncoding suits a team with a wire protocol that spans several languages and a latency budget, because generating the code for each side is cheaper and safer than maintaining parallel hand-written codecs. It is a poor fit for a single-language project with a couple of messages, where the generator and the build step are more machinery than the problem deserves, and a poor fit if you need a format that other teams already understand. Before you adopt it, read the format specification, run the benchmark suite yourself on your own data, and check the release history, because the newest tagged release is over a year older than the last commit.

## FAQ

### What is Fast Binary Encoding?

A toolchain rather than a library. You describe a domain model using base types, enums, flags and structs, then generate native code for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby or Swift, build that model into a library, and serialise objects in a compact binary format, with a JSON mode for web APIs and sender and receiver interfaces for building a protocol.

### Which types does the Fast Binary Encoding format support?

The base types are byte, bool, char, wchar, the 8 to 64 bit signed integers, float and double. The complex types are bytes, decimal, string, timestamp and uuid, the collections are array, vector, list, map and hash, and there is support for nullable and optional types, enums, flags and structs.

### How does Fast Binary Encoding compare with other serialisation formats?

The readme publishes a table in which Fast Binary Encoding serialises a sample message in 66 nanoseconds and deserialises in 82, against 558 and 359 for Cap'n Proto, 830 and 290 for FlatBuffers, 628 and 759 for Protobuf and 740 and 500 for JSON. The message is 234 bytes, which is larger than Protobuf's 120 for that case, and the figures come from the project author's own comparison repository.

### What does it take to build Fast Binary Encoding?

CMake, gcc, git, a code generation tool and Python 3, with clang and an IDE optional. The continuous integration builds on Linux with both clang and gcc, on macOS, and on Windows under Cygwin, MSYS2, MinGW and Visual Studio, and the project is MIT licensed.

## Sources

- [chronoxor/FastBinaryEncoding on GitHub](https://github.com/chronoxor/FastBinaryEncoding)
- [License: MIT](https://github.com/chronoxor/FastBinaryEncoding/blob/main/LICENSE)
- [Project website](https://chronoxor.github.io/FastBinaryEncoding)
- [README](https://github.com/chronoxor/FastBinaryEncoding/blob/main/README.md)
- [Releases](https://github.com/chronoxor/FastBinaryEncoding/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/chronoxor-fastbinaryencoding
