Back to Blog
Lesson 46 of the System Design: System Design Fundamentals course
ArchitectureSeptember 1, 20264 min read

Optimizing Network Communication: Serialization and Performance

Learn how to optimize network communication by choosing between JSON and Protobuf, minimizing payloads, and reducing round-trip times in your architecture.

networkingoptimizationserializationprotocolsystem-design
Networking cables plugged into a patch panel, showcasing data center connectivity.

Previously in this course, we explored analyzing resource bottlenecks to keep your services running lean. In this lesson, we shift our focus from the server's internal processing to the "wire"—the network communication between services—to minimize latency and overhead.

When systems scale, the way they talk to each other becomes a primary bottleneck. Every byte sent over the network costs CPU cycles to serialize, bandwidth to transport, and time to parse.

Comparing JSON and Protobuf

Most developers start with JSON because it’s human-readable and ubiquitous. However, JSON is a text-based format. Every time you send {"user_id": 12345}, you are sending the characters 'u', 's', 'e', 'r', '_', 'i', 'd' repeatedly. This is verbose and requires significant CPU overhead to parse.

Protocol Buffers (Protobuf) is a binary serialization format developed by Google. Instead of sending field names, it uses a schema to map data to numerical tags.

FeatureJSONProtobuf
FormatText-basedBinary
ReadabilityHuman-readableRequires tools to decode
SizeLarger (metadata overhead)Smaller (compact binary)
PerformanceSlower (string parsing)Faster (direct memory access)

When you use Protobuf, you define a .proto file that acts as a contract between services:

PROTOBUF
syntax = "proto3";

message User {
  int32 id = 1;
  string name = 2;
}

Because both the sender and receiver have this schema, they don't need to send the field names. They only send the raw values corresponding to the tags (1 and 2), leading to significantly smaller payloads.

Optimizing Payload Sizes and Round Trips

Low angle process of installation of modern carrier rocket in contemporary vehicle assembly building

Reducing your payload size is only half the battle. The number of round trips (the "chattiness" of your API) is often a bigger culprit in high latency. If a client needs to fetch a user profile, their settings, and their recent orders, making three separate HTTP requests involves three TCP handshakes and three potential network delays.

Technique 1: Request Batching

Instead of individual requests, design endpoints that accept or return arrays. A single /api/v1/user-data?ids=1,2,3 request is almost always faster than three individual calls, even if the payload is slightly larger.

Technique 2: Partial Responses (Field Selection)

If a resource has 50 fields but the mobile client only needs two, don't send the whole object. Allow the client to specify fields, or create "projection" endpoints. This reduces serialization time and network egress costs.

Worked Example: Moving to Binary

In our running project, let’s consider our User service. We currently return JSON. To optimize, we can implement a simple binary serialization using a format like MessagePack (which is often easier to drop into existing projects than full Protobuf).

PYTHON
import msgpack

# The data we need to send
user_data = {"id": 12345, "name": "Alice", "role": "admin"}

# JSON approach:
# {"id": 12345, "name": "Alice", "role": "admin"} -> 45 bytes

# Binary approach:
binary_data = msgpack.packb(user_data)
# Binary data is ~20-30% smaller and parses much faster

By switching from JSON to a binary format for internal service-to-service communication, we reduce the time spent in serialization logic and lower the pressure on our network interfaces.

Hands-on Exercise

  1. Pick an existing API endpoint in your project.
  2. Measure the response size using curl -v or your browser's Network tab.
  3. If the payload is larger than 1KB, create a "minified" version by removing unnecessary fields.
  4. If you have multiple calls to the same service occurring sequentially, refactor them into a single batch request and measure the total round-trip time (RTT) reduction.

Common Pitfalls

Close-up of a triangular warning sign indicating a slippery surface, fixed to a wooden post.

  • Premature Optimization: Don't switch to Protobuf if your service is IO-bound by a database query that takes 200ms. The serialization speedup (saving 1ms) won't be noticeable.
  • Lack of Tooling: Binary formats are harder to debug. Use tools like grpcurl or interceptors to view your traffic when debugging issues.
  • Schema Evolution: When using Protobuf, never change the tag numbers of existing fields. That breaks backward compatibility immediately.

FAQ

Q: Is JSON ever better than Protobuf? A: Yes. If your API is public-facing and intended for third-party developers, JSON is the industry standard for usability. Use binary protocols for internal microservice communication where you control both ends.

Q: Does compression (Gzip/Brotli) make JSON efficient enough? A: Compression helps with transfer size, but it doesn't help with CPU-heavy parsing costs. Binary formats provide both smaller size and lower CPU usage.

Recap

Team members presenting a project in a modern office setting with a focus on collaboration.

Networking optimization is about reducing the "tax" paid on every message. By moving to binary serialization and reducing the number of requests via batching, you decrease the latency of your distributed system. Always measure the overhead before implementing complex changes, and prioritize reducing the number of round trips first.

Up next: We will discuss Managing Secret Keys and Configuration to ensure our optimized services remain secure.

Similar Posts