Data Serialization Formats (Protobuf, Thrift)

Published: 5/14/2026 | Author: Alex Merced

RPCschema evolutionbinary encodingmicroservices

Introduction to Serialization

When a Python application running on Server A needs to send a customer profile (like a User object containing a name and age) to a Java application running on Server B, it cannot simply push its computer memory over the internet. Memory structures are unique to specific programming languages and CPU architectures.

The data must be translated into a universal format (like a string of characters or a stream of raw bytes) that can be transmitted over a network wire. This translation process is called Serialization (or Encoding). When Server B receives the stream and reconstructs the User object in Java, it is called Deserialization (or Decoding).

The Inefficiency of JSON

For the vast majority of web development, JSON (JavaScript Object Notation) is the default serialization format.

{"user_id": 12345, "name": "Alex", "is_active": true}

JSON is phenomenal because it is human-readable. You can open a JSON file in a text editor and immediately understand the data. However, JSON is terrible for high-performance, internal microservice communication.

  1. Massive Overhead: To send the number 12345, JSON sends the literal characters 1, 2, 3, 4, 5. It also sends all the quotation marks, colons, and curly braces. This consumes massive amounts of network bandwidth.
  2. Slow Parsing: Server B has to read the text character by character, figure out where the strings end, and convert the text “12345” back into an actual integer in CPU memory. This burns massive CPU cycles.

The Solution: Binary Serialization

For massive, high-throughput distributed systems (like Google’s internal microservices or an Apache Kafka stream), engineers use Binary Serialization Formats like Protocol Buffers (Protobuf) (developed by Google) or Apache Thrift (developed by Facebook).

These formats abandon human readability in exchange for blistering machine speed.

How Protobuf Works

Instead of sending the field names in every single message (like "user_id":), Protobuf uses a Schema Contract. The developer writes a .proto file defining the structure:

message User {
  int32 user_id = 1;
  string name = 2;
  bool is_active = 3;
}

Using a compiler, this schema generates native Python and native Java code. When Server A sends the data, it does not send the string "user_id". It simply sends the binary tag 1 followed instantly by the raw binary representation of the integer 12345.

  • Bandwidth: The payload size is often 5x to 10x smaller than JSON.
  • Speed: Because there is no text parsing required, the CPU deserializes the binary stream into a native Java object almost instantaneously.

Schema Evolution

The true superpower of Protobuf and Thrift is Forward and Backward Compatibility.

In a company with 500 microservices, if Team A decides to add a “phone_number” field to the User object, they cannot update all 500 microservices simultaneously.

With JSON, adding a field might crash older services that don’t know how to parse it. With Protobuf, schemas use numeric tags (user_id = 1, phone_number = 4). If an old Java service receives a message containing Tag 4, it simply ignores it and processes the rest of the message perfectly. This allows massive engineering organizations to independently upgrade microservices without breaking the entire enterprise architecture.

Conclusion

While JSON remains the undisputed king of public-facing REST APIs and web browsers, Binary Serialization formats (Protobuf, Thrift, Avro) are the invisible plumbing of the modern backend. By enforcing strict schema contracts and compressing data into machine-optimized binary streams, these formats provide the extreme performance and safe schema evolution required to run massive, heavily trafficked microservice and big data architectures.

Deepen Your Knowledge

Ready to take the next step in mastering the Data Lakehouse? Dive deeper with my authoritative guides and practical resources.

Explore Alex's Books