How LinkedIn Reduced Microservice Latency by 60% with Protocol Buffers

Arpit Bhayani

Arpit Bhayani

Jun 28, 2024 • 7 min read

Play

How LinkedIn Reduced Microservice Latency by 60% with Protocol Buffers

Page load times and downstream service latencies are critical metrics at hyper-scale tech companies. At LinkedIn, responsive pages directly correlate with user engagement, conversion, and overall experience.

To power millions of simultaneous interactions, LinkedIn relies on a distributed microservices ecosystem rather than a monolithic backend. Their internal communication layer runs on Rest.li, a proprietary REST framework built in-house and open-sourced by LinkedIn. In production, this infrastructure manages over 50,000+ endpoints.

Historically, communication between services communicating through Rest.li relied on JSON (JavaScript Object Notation). Despite its ubiquity, JSON became a major bottleneck. By re-evaluating their serialization layer and migrating to Google Protocol Buffers (Protobuf), LinkedIn achieved a staggering 60% improvement in service latency.

Here is a detailed breakdown of the bottlenecks of JSON at scale, LinkedIn’s architectural criteria, how they rolled out the change without downtime, and why you don’t need gRPC to benefit from Protobuf.


The Hidden Tax of JSON at Scale

JSON is widely regarded as the lingua franca of modern APIs. It offers exceptional human readability and universal support across virtually every programming language. However, when deployed across tens of thousands of microservices handling billions of transactions per day, its design characteristics impose severe performance penalties.

JSON Payload (Textual, Repetitive Metadata):
{
  "id": 123456789,
  "name": "Alice"
}
--> 38+ bytes transferred across the wire (including whitespace/keys)

Binary Payload (Protobuf - Field Tags + Dense Encoding):
[tag:value][tag:value]
--> Fraction of the byte footprint

1. Verbose and Redundant Syntax

JSON is a textual, schema-less (self-describing) format. In every single request and response, field names must be fully written out inside quotes ("user_identifier"), accompanied by structural delimiters such as colons, commas, braces ({}), and brackets ([]). Multiplying these repeated keys by thousands of internal microservice hops consumes massive amounts of unnecessary bandwidth.

2. Inefficient Data Density

Textual encoding is not densely packed. Consider a 32-bit integer value: 123456789.

  • In JSON (Text): Each digit is encoded as an individual ASCII/UTF-8 character, taking 9 bytes (0x31 0x32 0x33...) on the wire.
  • In Binary: A standard 32-bit integer fits in just 4 bytes. If using variable-length zigzag encoding (varints), smaller numbers require even less.

At scale, transferring millions of numeric IDs, timestamps, and counters as raw strings results in significant network bloat.

3. Parsing and Deserialization Overhead

Parsing JSON requires stateful string scanning, tokenization, bracket matching, string unescaping, and dynamic type coercion. Furthermore, incremental parsing of complex JSON documents is inefficient; parsers typically scan entire chunks of data into memory before mapping them to typed domain models. This consumes significant CPU cycles and generates transient heap allocations that trigger frequent garbage collection (GC) pauses.

4. The Compression Fallacy

An intuitive countermeasure is to enable compression algorithms like Gzip, Zstandard, or Snappy over HTTP. While compression reduces payload size across the wire, it is not free:

  • Compressing data requires spare CPU cycles on the sending service.
  • Decompressing requires CPU cycles and RAM on the receiving service.
  • In latency-critical distributed call graphs where calls fan out to dozens of internal services, the computational latency of compression and decompression can easily eclipse the network transmission savings.

LinkedIn’s Evaluation Criteria for an Alternative

When searching for an alternative to JSON, LinkedIn defined three strict architectural requirements:

  1. Ultra-Compact Payload Sizes: Eliminate repeated metadata, pack primitives into dense binary representations, reduce egress/ingress bandwidth, and minimize network serialization delay.
  2. High-Throughput Serialization and Deserialization: Reduce the CPU overhead of translating wire bytes into native objects. Deserializers should quickly traverse byte buffers without complex scanning logic.
  3. Broad Multi-Language Support: First-class code generation and runtime libraries for Java, Python, C++, Go, and other internal languages.

LinkedIn selected Google Protocol Buffers (Protobuf) as their target serialization standard.


Separating Serialization from Transport: Protobuf Without gRPC

A common industry misconception is that Protocol Buffers can only be used alongside gRPC over HTTP/2.

In reality, Protobuf is purely an encoding and serialization mechanism. It defines a binary wire format and generates domain classes based on .proto schema definitions. You do not need to replace your HTTP client, ingress proxies, or service orchestration layers to leverage Protobuf.

+-----------------------------------------------------------+
|                    LinkedIn Microservice                  |
+-----------------------------------------------------------+
                              |
               [ Rest.li Communication Framework ]
                              |
            +-----------------+-----------------+
            |                                   |
    [ HTTP / REST Layer ]             [ Protobuf Serialization ]
    (Existing Transport)               (Replaced JSON Payloads)

LinkedIn recognized this separation of concerns. Instead of undergoing a risky, wholesale migration from their Rest.li REST framework to gRPC, they decoupled the transport from the payload format: they kept Rest.li intact and swapped out the internal serialization engine from JSON to Protobuf.


The Zero-Downtime Rollout Strategy

Migrating 50,000+ endpoints across hundreds of independent engineering teams requires a zero-downtime, backwards-compatible transition mechanism.

sequenceDiagram
    autonumber
    participant Client as Rest.li Client
    participant Server as Rest.li Server

    Note over Client,Server: Phase 1: Framework Upgraded (JSON default)
    Client->>Server: POST /resource (Content-Type: application/json)
    Server-->>Client: 200 OK (Content-Type: application/json)

    Note over Client,Server: Phase 2: Client opts into Protobuf
    Client->>Server: POST /resource (Content-Type: application/x-protobuf2)
    Server->>Server: Match header -> Use Protobuf Decoder
    Server-->>Client: 200 OK (Content-Type: application/x-protobuf2)

    Note over Client,Server: Phase 3: Instant Fallback on Failure
    Client->>Server: POST /resource (Content-Type: application/json)
    Server-->>Client: 200 OK (Content-Type: application/json)

Step 1: Upgrading the Base Framework (Rest.li)

Support for Protobuf serialization and deserialization was first implemented directly within the core Rest.li framework. All downstream services then upgraded their Rest.li dependency version. At this stage, services retained JSON as the default format, but gained the native capability to decode Protobuf payloads if received.

Step 2: Content Negotiation via HTTP Headers

To handle dynamic, dual-format communication between un-migrated clients and upgraded servers, LinkedIn used standard HTTP content negotiation:

  • Request Header: When a client opted to send a Protobuf-encoded payload, it marked the request with:
    Content-Type: application/x-protobuf2
  • Server Dispatching: The server inspected the Content-Type header. If the header indicated application/x-protobuf2, the request body was routed to the Protobuf decoder. If omitted or set to application/json, it fell back to the legacy JSON decoder.
  • Response Negotiation: Similarly, servers used the Accept and Content-Type response headers to return Protobuf data once downstream consumers verified readiness.

Step 3: Canary Deployments and Failsafe Rollbacks

Teams enabled Protobuf service-by-service using progressive canaries. If a service encountered deserialization discrepancies, malformed payloads, or integration edge cases, teams could instantly toggle the client configurations back to standard JSON without deploying code fixes or rolling back binaries.


Impact and Results

By simply changing the serialization format while keeping their existing service mesh and networking transport stable, LinkedIn achieved:

MetricJSON ImplementationProtobuf ImplementationResult
LatencyBaselineReduced by ~60%60% Latency Improvement
Wire SizeLarge (repetitive string keys, uncompressed text)Highly compact binary varintsSubstantial Bandwidth Reduction
CPU UtilizationHigh (string parsing, object allocations)Low (direct binary offset decoding)Increased Service Throughput

Key Takeaways for System Architects

  1. Serialization Is Often the Silent Bottleneck: In high-throughput, microservice-heavy environments, CPU cycles are predominantly spent encoding and decoding objects, not just executing business logic.
  2. Protobuf Is Independent of gRPC: Protobuf can be embedded inside standard HTTP/1.1 REST calls, message brokers (Kafka), or web sockets without rewriting routing, load balancing, or transport architectures.
  3. Content Negotiation Enables Zero-Downtime Upgrades: Standard HTTP headers (Content-Type and Accept) provide an elegant mechanism for gradual protocol migrations across distributed teams.
  4. Solve One Constraint at a Time: LinkedIn proved that decoupling the serialization upgrade from the transport upgrade (deferring gRPC and HTTP/2 for later) minimized operational risk while unlocking the majority of the performance gains immediately.
Arpit Bhayani

Principal Engineer II at Razorpay - building Agent Studio, Ex-staff engg at GCP Memorystore & Dataproc, Creator of DiceDB, ex-Amazon Fast Data, ex-Director of Engg. SRE and Data Engineering at Unacademy. I spark engineering curiosity through my no-fluff engineering videos on YouTube and my courses