This page follows the Apache Avro specification, both the 1.12.0 release documentation and the current text in the Avro repository, read 2026-11-12; they agree on everything below. The variable-length integers follow the Lucene 3.5 VInt that the specification links, read 2026-11-12. Binary Avro data has no field names or type information, so reading it needs the schema it was written with, which a container file carries in its header.
Schema types
| Type | Binary encoding |
|---|---|
null | Nothing. |
boolean | One byte, 0 or 1. |
int, long | Zig-zag, then variable length: 7 bits per byte, low bits first, high bit set when more follow. 0 → 00, −1 → 01, 1 → 02, −64 → 7F, 64 → 80 01. |
float, double | 4 or 8 bytes IEEE 754, little-endian. |
bytes, string | A long length, then the bytes (UTF-8 for strings). |
record | The fields in schema order, nothing between. Attributes: name, namespace, doc, aliases, fields (each name, type, doc, default, order, aliases). |
enum | An int: the index in symbols. Optional default symbol for readers. |
array | Blocks: a long count, then that many items; a count of 0 ends. A negative count means its absolute value, followed by the block’s size in bytes, so readers can skip it. |
map | Blocks as for arrays, each entry a string key and a value of type values. |
| union | Written in JSON as an array of types. An int giving the zero-based index of the branch, then the value. (The specification notes that C and C++ implementations treat the index as an int, though in theory it is a long.) |
fixed | Exactly size bytes. |
Logical types
logicalType | On | Meaning |
|---|---|---|
decimal | bytes, fixed | Two’s complement big-endian unscaled value, with precision and scale |
big-decimal | bytes | Decimal with its scale stored in the value: the bytes hold an Avro bytes value (two’s complement big-endian unscaled value) followed by the scale as an Avro int |
uuid | string, fixed(16) | UUID |
date | int | Days since 1970-01-01 |
time-millis, time-micros | int, long | Time of day: milliseconds or microseconds after midnight |
timestamp-millis, -micros, -nanos | long | Instant: units since the Unix epoch, 1970-01-01 00:00:00 UTC |
local-timestamp-millis, -micros, -nanos | long | Timestamp in a local time zone, whichever is considered local: units from 1970-01-01 00:00:00 |
duration | fixed(12) | Three unsigned 4-byte little-endian numbers: months, days, milliseconds |
A reader that does not know a logical type uses the underlying type.
Object container file
| Part | Encoding |
|---|---|
| Magic | 4F 62 6A 01: Obj and 1. |
| Metadata | A map of bytes. avro.schema: the schema as JSON. avro.codec: the codec (absent means null). Keys starting avro. are reserved. |
| Sync marker | 16 random bytes. |
| Blocks | A long count of objects, a long size in bytes of the serialised objects after compression, the objects, then the 16-byte sync marker. |
| Codec | Block data |
|---|---|
null | Not compressed. Required of every implementation. |
deflate | Deflate as in RFC 1951, not the RFC 1950 zlib format, so no checksum. Required. |
bzip2 | bzip2. |
snappy | Snappy, followed by a 4-byte big-endian CRC-32 of the uncompressed data. |
xz | XZ. |
zstandard | Zstandard. |
Single-object encoding
For one value outside a container (for example a message): the marker
C3 01 (single-object format version 1), the 8-byte little-endian
CRC-64-AVRO (64-bit Rabin) fingerprint of the object’s schema, then the binary value.
Readers use the marker to tell an Avro payload apart before looking the schema up by
its fingerprint.