By Gerard King | www.gerardking.dev
If you’ve worked with APIs or data interchange formats like JSON or XML, you know they’re human-readable but not always the most efficient when it comes to size or speed. That’s where Protocol Buffers, or Protobuf, come in.
Originally developed by Google, Protobuf is a method for serializing structured data that’s fast, compact, and cross-platform. Whether you're building microservices, mobile apps, or high-performance systems, Protobuf can help make your data communication lean and mean.
At its core, Protobuf is a way to define structured data and then serialize it into a binary format that’s both compact and fast to transmit. Think of it like JSON or XML, but optimized for machines — not humans.
You define your data schema in a .proto file, then compile it into code for your programming language of choice (Python, Go, Java, etc.). That code lets you easily serialize and deserialize data across systems and services.
Feature
JSON
XML
Protobuf
Readability
✅ Human-friendly
✅ Human-friendly
❌ Machine-friendly
Performance
❌ Slower
❌ Slowest
✅ Fastest
Size
❌ Verbose
❌ Very verbose
✅ Extremely compact
Type Safety
❌ Loose
⚠️ Mixed
✅ Strongly typed
Versioning
⚠️ Manual
⚠️ Limited
✅ Built-in
Compile it using the protoc compiler to generate code for your target language.
Use that code to serialize (write) and deserialize (read) your data.
Cross-platform & Language-neutral: Ideal for polyglot environments.
Compact: Great for bandwidth-constrained systems (IoT, mobile).
Fast: Binary format means faster serialization/deserialization.
Strong typing: Makes evolving and maintaining APIs cleaner.
Built-in versioning: Old clients can still talk to new services.
Building microservices or internal APIs
Systems where performance and bandwidth matter
Mobile apps, IoT, or real-time data pipelines
Logging, analytics, and data storage where space adds up
Public APIs where readability and debuggability matter
Rapid prototyping or tools without Protobuf support
Protocol Buffers might seem intimidating at first — especially if you’re used to the comfort of JSON — but they shine when performance and structure matter. Once you get into the groove of defining .proto files and generating code, the gains in speed and efficiency are hard to ignore.
If you're serious about building scalable systems, it's worth adding Protobuf to your toolkit.
Check out more dev tools, backend tips, and system design content over at www.gerardking.dev.
What is Protobuf used for?
Protobuf vs JSON performance
How to write a .proto file
Protobuf tutorial for beginners
gRPC vs REST with Protobuf
Protocol Buffers serialization example
Why is Protobuf faster than JSON?
When not to use Protocol Buffers
How to install protoc compiler
By Gerard King | www.gerardking.dev
When building APIs today, one of the most critical decisions is how your services exchange data. Two common formats stand out:
JSON (JavaScript Object Notation): Easy to read, widely supported.
Protocol Buffers (Protobuf): Google’s compact, binary serialization format.
If performance, efficiency, and scalability matter to your stack, it’s worth understanding how these two stack up.
JSON is text-based and easy to work with, but that also means it's relatively slow to parse, especially in large payloads or real-time systems.
Protobuf, on the other hand, uses a binary format that machines can read and write much faster. When microservices need to talk to each other quickly, speed is crucial — and Protobuf is built for it.
JSON parsing: 2–5x slower than Protobuf in many benchmarks
Protobuf is ideal for streaming data, gRPC, and high-frequency requests
JSON includes field names in every payload, which adds overhead — especially when sending large arrays of objects.
Protobuf uses field numbers and a compact binary format. This means you can transmit the same data using 30–60% less bandwidth compared to JSON.
// JSON
{
"id": 123,
"name": "Alice",
"email": "alice@example.com"
}
// Protobuf binary (unreadable to humans but ~60% smaller)
This space saving adds up fast in mobile apps, IoT, or systems dealing with millions of transactions per day.
Feature
JSON
Protobuf
Type System
Loose (e.g. everything's a string)
Strong (int32, string, etc.)
Schema
Optional, informal
Required .proto schema
Versioning
Manual
Built-in field numbers
Validation
Done in app code
Enforced by schema
JSON’s flexibility is helpful in prototyping, but it can become a liability in large systems where data integrity matters. Protobuf ensures consistent, validated data across services.
Use Case
Use Protobuf
Use JSON
Microservices
✅ Yes
⚠️ Okay (less efficient)
Mobile or IoT apps
✅ Yes
❌ Often too large
Public APIs
❌ Binary format is opaque
✅ Human-readable
Internal APIs
✅ Fast & compact
⚠️ Easier debugging
Prototyping / Testing
❌ Slower setup
✅ Quick and simple
Feature
Protobuf
JSON
Speed
✅ Fast
❌ Slower
Size
✅ Compact
❌ Verbose
Structure
✅ Strongly typed
❌ Loosely typed
Readability
❌ Binary
✅ Human-friendly
Tooling
⚠️ Needs compiler
✅ Built-in in most languages
Choosing between Protocol Buffers and JSON comes down to your use case.
If you’re building high-performance systems where speed and size matter, Protobuf is the clear winner.
If you need human-readable payloads, easy debugging, or quick setup, JSON remains a solid option.
For internal APIs and microservices, especially in production-grade architectures, I lean heavily toward Protobuf. You can always layer in tools like gRPC, which is built on Protobuf, for even more structure and efficiency.
More dev content like this at www.gerardking.dev
Protobuf vs JSON performance benchmark
gRPC with Protobuf vs REST with JSON
Is Protobuf better than JSON?
How to convert JSON to Protobuf
Protobuf vs JSON size comparison
When to use Protobuf in microservices
Advantages of Protocol Buffers
Human-readable alternatives to Protobuf
By Gerard King | www.gerardking.dev
When you think about modern APIs, your first thought is probably JSON — and for good reason. It's readable, flexible, and supported almost everywhere. But when you're building systems that need speed, structure, and scalability, there's a better tool in the box: Protocol Buffers, or Protobuf.
Developed by Google, Protobuf is a method for serializing structured data that’s fast, efficient, and ideal for cross-language communication. If you're building microservices, mobile apps, or data-heavy backends, Protobuf could seriously level up your architecture.
Protocol Buffers are a language-neutral, platform-neutral format for defining and exchanging structured data. You define your data’s structure in a .proto file, compile it into your programming language of choice, and use it to serialize and deserialize binary data.
Think of it like JSON — but smaller, faster, and stricter.
Define your schema in a .proto file:
syntax = "proto3";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
}
Compile it using the Protobuf compiler (protoc) to generate code.
Use the generated code to easily serialize (write) and deserialize (read) data across systems.
Feature
JSON
Protobuf
Speed
Slower
✅ Much faster
Size
Larger
✅ More compact
Schema
Informal
✅ Strict & enforced
Readability
✅ Human-readable
❌ Binary format
Versioning
Manual
✅ Built-in
Protobuf’s compact binary format makes it ideal for performance-critical environments, while JSON’s readability is great for quick testing and public-facing APIs.
✅ Ideal for:
Internal APIs and microservices
Mobile and IoT applications
Real-time systems or streaming
Storing large volumes of structured data
🚫 Not ideal for:
Public APIs where readability matters
Quick debugging or prototyping
As your systems scale, performance bottlenecks start to matter. Network latency, payload size, and CPU cycles all add up. Protobuf gives you a clear advantage in those areas — without sacrificing flexibility or maintainability.
And with native support in tools like gRPC, using Protobuf today means you're building on infrastructure designed for tomorrow.
Protocol Buffers are more than just an alternative to JSON — they're a powerful standard for efficient, structured communication. The learning curve is minimal, and the performance benefits are real. Whether you're shipping data across services or storing it at scale, Protobuf helps you do it better.
For more backend tips, dev tools, and architecture guides, visit www.gerardking.dev
What is Protocol Buffers used for?
Protobuf vs JSON speed test
How to define a .proto schema
gRPC and Protobuf explained
How to install protoc compiler
Protobuf serialization example
Advantages of binary serialization
When to use Protobuf vs JSON
By Gerard King | www.gerardking.dev
If you're starting with Protocol Buffers (Protobuf), one of the first things you'll encounter is the .proto file. This single file is the blueprint for your data — defining what it looks like, how it's structured, and how it evolves over time.
In this guide, I’ll break down what a .proto file is, how to write one, and why it matters for modern API development.
A .proto file is a schema definition written in Protocol Buffers language. It describes the shape of your data — much like a class or data model — but in a language-neutral format. Once written, it can be compiled into code for various programming languages.
Here’s a simple example:
syntax = "proto3";
message User {
string name = 1;
int32 id = 2;
string email = 3;
}
syntax = "proto3";
Declares the version of Protobuf you're using (proto2 and proto3 are available — proto3 is the modern standard).
message User { ... }
Defines a structured object (like a class) called User.
string name = 1;
Each field has:
A type (string, int32, etc.)
A name
A unique field number
Field numbers are used in the binary format, not the names. They're critical for:
Efficient encoding
Backward/forward compatibility
Schema evolution
You can remove or deprecate fields, but never reuse a field number for a different purpose.
Type
Description
int32
32-bit integer
int64
64-bit integer
float
32-bit floating point
double
64-bit floating point
string
UTF-8 text
bool
true/false
bytes
Arbitrary binary data
Protobuf allows nested structures and lists:
message Post {
string title = 1;
repeated string tags = 2;
message Author {
string name = 1;
string email = 2;
}
Author author = 3;
}
repeated means an array or list of values.
Nested message types let you create more complex structures.
You can also define enums:
enum Status {
UNKNOWN = 0;
ACTIVE = 1;
INACTIVE = 2;
}
message User {
string name = 1;
Status status = 2;
}
Always start enums at 0 — it’s the default value.
When removing fields, reserve their numbers:
message User {
reserved 4, 5;
reserved "username", "profile_url";
}
This avoids conflicts when future versions of the schema are deployed.
Use the protoc compiler to generate code:
protoc --python_out=. user.proto
Replace --python_out with the target language you need (e.g., --go_out, --java_out, etc.).
.proto files are the foundation of any Protobuf-based system. They're not just technical definitions — they're contracts between services, teams, and systems. A clean, well-managed .proto schema keeps your APIs fast, version-safe, and language-agnostic.
Once you master them, you're no longer just writing data — you're designing scalable communication.
Explore more dev tools and architecture tips at www.gerardking.dev
How to write a .proto file
Protobuf schema best practices
What are field numbers in Protobuf
Nested messages in .proto files
Protocol Buffers repeated field example
Protobuf enum usage
Compiling .proto files to Python/Go
Protobuf schema evolution strategy
By Gerard King | www.gerardking.dev
If you’ve ever looked at a JSON or XML payload and thought, “This is way too much for what I need,” you’re not alone. That’s exactly the kind of problem Protocol Buffers (Protobuf) were designed to solve.
Protobuf takes structured data and converts it into a compact, binary format that’s optimized for speed and size. But how exactly does that work?
In this article, I’ll walk you through how Protocol Buffers serialize data, and why this method is so much more efficient than traditional formats.
Serialization is the process of converting a data structure or object into a format that can be stored or transmitted — and then rebuilt later (deserialization). Protobuf takes a schema-first approach to do this as efficiently as possible.
Here’s what happens when you serialize a Protobuf message:
message User {
string name = 1;
int32 id = 2;
bool is_active = 3;
}
This schema is written in a .proto file and compiled into code for your programming language of choice.
Field numbers (= 1, = 2, etc.) are critical. They’re used to identify fields in the binary data instead of the field names — saving space and enabling versioning.
Instead of sending:
{
"name": "Alice",
"id": 123,
"is_active": true
}
Protobuf encodes that into something like:
0A 05 41 6C 69 63 65 10 7B 18 01
That might look like gibberish, but each piece is carefully packed to reduce size:
0A = field 1 (name) + wire type
05 = length of the string
41 6C 69 63 65 = UTF-8 bytes for "Alice"
10 = field 2 (id) + wire type
7B = 123 (encoded as varint)
18 = field 3 (is_active) + wire type
01 = true
Wire types tell the decoder how to interpret the next bytes. Common types include:
Wire Type
Description
0
Varint (int32, int64, bool)
1
64-bit (double, fixed64)
2
Length-delimited (strings, bytes, nested messages)
5
32-bit (float, fixed32)
Fields with default values (e.g., false, 0, empty string) are not serialized at all. This cuts down on unnecessary bytes and keeps payloads lean.
Because Protobuf uses field numbers and types instead of names, the deserializer can quickly map incoming binary data back into structured objects — without needing to scan full strings or guess formats.
Protobuf is forwards and backwards compatible:
New fields can be added without breaking old clients.
Unknown fields are skipped when deserializing, making updates safe and seamless.
Speed: Protobuf can parse messages up to 10x faster than JSON.
Size: Serialized Protobuf messages are often 60–80% smaller.
Consistency: The schema ensures predictable, well-typed data across systems.
This makes Protobuf ideal for high-performance APIs, streaming data, and resource-constrained environments like mobile or IoT.
Protobuf isn’t just “binary JSON.” It’s a fundamentally smarter way to move structured data between services. By skipping the overhead of names, using efficient encodings, and leaning on a strict schema, Protobuf gives you data serialization that’s built for scale.
If you’re serious about performance or designing systems that will evolve cleanly over time, understanding how Protobuf serializes data is key.
More backend engineering insights at www.gerardking.dev
How does Protobuf serialization work
Protobuf wire format explained
Protobuf vs JSON performance
How to decode Protobuf binary
Varint encoding in Protobuf
Protobuf serialization example
Why is Protobuf so compact
Protocol Buffers backward compatibility
By Gerard King | www.gerardking.dev
Once you’ve defined your data in a .proto file, the next step is turning that schema into actual, working code. That’s where the protoc compiler comes in — and mastering it is key to building efficient, cross-language systems with Protocol Buffers (Protobuf).
In this guide, I’ll walk you through how protoc works, how to use it across different languages, and a few power tips to speed up your workflow.
protoc is the Protocol Buffers compiler. It takes your .proto files and generates source code in the language of your choice — so your app can serialize and deserialize Protobuf messages with ease.
Think of it as the glue between your schema and your actual application code.
First, you need to install the protoc binary.
brew install protobuf
sudo apt install protobuf-compiler
https://github.com/protocolbuffers/protobuf/releases
Let’s say you have a file called user.proto:
syntax = "proto3";
message User {
string name = 1;
int32 id = 2;
}
To generate code in different languages:
protoc --python_out=. user.proto
protoc --go_out=. user.proto
protoc --js_out=import_style=commonjs:. user.proto
protoc --java_out=. user.proto
The output will be a .pb.* file in your chosen language that gives you classes and methods to work with your message structure.
If your .proto files are organized in folders or reference other .proto files, use the --proto_path flag:
protoc --proto_path=schemas --python_out=out schemas/user.proto
This sets schemas/ as the root for imports and outputs the result to the out/ directory.
Protobuf also powers gRPC, and you can generate server/client stubs with plugins.
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. user.proto
protoc --go_out=. --go-grpc_out=. user.proto
Make sure you have the necessary plugins installed (grpcio-tools for Python, protoc-gen-go and protoc-gen-go-grpc for Go).
You don’t need to remember all these flags every time. Automate compilation with a Makefile, shell script, or npm/yarn task.
Example Makefile:
PROTO_SRC=user.proto
PY_OUT=./generated
protoc:
protoc --python_out=$(PY_OUT) $(PROTO_SRC)
Use clear, consistent field numbers — and never reuse deleted ones.
Separate schema files into a protos/ or schemas/ folder.
Use reserved to prevent accidental reuse of removed fields or names.
Regenerate code on every schema change — Protobuf isn’t forgiving with mismatches.
The protoc compiler is the gateway between your .proto schemas and your production-ready code. Once you’ve got a handle on how to use it, generating cross-language data models becomes quick and seamless.
Whether you're working in Python, Go, Java, or TypeScript, protoc is your build-time friend — and mastering it means one less bottleneck in your API pipeline.
More dev tools, backend tips, and Protobuf tutorials at www.gerardking.dev
How to install protoc compiler
protoc Python example
protoc Go plugin setup
protoc vs gRPC tools
How to compile .proto files
protoc include paths and imports
Automate protoc compilation
Generate gRPC code with protoc