DEV Community

Cover image for 🚀 REST vs gRPC Performance in Go: A Practical Benchmark-Driven Guide
Chiman Jain
Chiman Jain

Posted on

🚀 REST vs gRPC Performance in Go: A Practical Benchmark-Driven Guide

When building high-performance microservices in Go, one question inevitably comes up:

Should you use REST or gRPC?

This isn’t just an architectural debate it directly impacts latency, throughput, infrastructure cost, and scalability. In this post, we’ll break down REST vs gRPC performance using real benchmarks, practical Go examples, and production insights.


🧠 Understanding the Core Difference

Before diving into benchmarks, it’s important to understand why performance differs.

REST

  • Uses HTTP/1.1 (typically)
  • Data format: JSON (text-based)
  • Stateless, resource-oriented

gRPC

  • Uses HTTP/2
  • Data format: Protocol Buffers (binary)
  • Supports streaming (bi-directional)

Why This Matters

  • Binary serialization is more compact and faster to parse
  • HTTP/2 enables multiplexing multiple requests over a single connection
  • Reduced payload size = faster network transfer

⚙️ Benchmark Setup (Go)

Reference repository:

👉 https://github.com/chimanjain/go-rest-grpc-bencmark

This project benchmarks:

  • REST API (JSON over HTTP)
  • gRPC API (Protobuf over HTTP/2)

Typical Test Conditions

  • Concurrent clients
  • Small to medium payload sizes
  • High request volume
  • Controlled environment for fair comparison

📊 Benchmark Results (What Actually Happens)

Across benchmarks (including the referenced repo), a few consistent patterns emerge.

🔥 Key Observations

  • gRPC shows:

    • Lower latency
    • Higher throughput
    • Better CPU efficiency
  • REST:

    • Performs well at low scale
    • Degrades faster under heavy load due to parsing and connection overhead

🧾 Why gRPC Is Faster

Factor REST gRPC
Serialization JSON (text) Protobuf (binary)
Transport HTTP/1.1 HTTP/2
Payload Size Larger Smaller
Parsing Cost Higher Lower
Streaming Limited Native

🧪 Sample Go Implementations

🌐 REST Example (net/http)

package main

import (
    "encoding/json"
    "net/http"
)

type User struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

func getUser(w http.ResponseWriter, r *http.Request) {
    user := User{ID: "1", Name: "John"}

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(user)
}
Enter fullscreen mode Exit fullscreen mode

⚡ gRPC Example

package main

import (
    "context"
    pb "example/proto"
)

type server struct {
    pb.UnimplementedUserServiceServer
}

func (s *server) GetUser(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) {
    return &pb.UserResponse{
        Id:   "1",
        Name: "John",
    }, nil
}
Enter fullscreen mode Exit fullscreen mode

⚖️ Key Difference

  • REST: manual serialization using encoding/json
  • gRPC: strongly typed, auto-generated code via .proto files

📈 Performance Deep Dive

1. Latency

  • gRPC typically achieves lower p99 latency
  • Especially noticeable with:

    • High concurrency
    • Small payloads

Reason: smaller payloads + faster serialization


2. Throughput

  • gRPC supports more requests per second
  • HTTP/2 multiplexing reduces connection overhead

3. CPU Usage

  • JSON parsing is CPU-intensive
  • Protobuf significantly reduces CPU overhead

4. Network Efficiency

  • Protobuf messages are smaller than JSON
  • Less bandwidth usage leads to faster transfers

🤔 When REST Performs Just Fine

Despite the performance gap, REST is still a solid choice in many scenarios:

  • Low to moderate traffic
  • Large payloads (compression reduces differences)
  • Public APIs and browser-based clients
  • Faster development and easier debugging

In many real-world systems, the performance difference is not critical.


🧩 Real-World Tradeoffs

Choose gRPC when:

  • Internal microservices communication
  • High-throughput or low-latency systems
  • Real-time streaming (e.g., chat, telemetry)
  • Strong contract enforcement is needed

Choose REST when:

  • Building public-facing APIs
  • Browser compatibility is required
  • Simplicity and ecosystem support matter

Common Industry Pattern

Use gRPC internally and REST externally

This gives you performance where it matters and compatibility where it’s needed.


🧠 Key Takeaways

  • gRPC is faster by design due to:

    • HTTP/2
    • Protobuf serialization
    • Efficient connection handling
  • REST is:

    • Simpler
    • More widely supported
    • “Fast enough” for many applications

🏁 Final Thoughts

Performance decisions should always be context-driven.

  • Building high-scale backend systems? → gRPC
  • Building public APIs? → REST

The best architecture often combines both.


🔗 References


💬 If you’ve run your own benchmarks in Go, feel free to share your results!

Top comments (1)

Collapse
 
satandev profile image
SatanDev

Por favor sube más comparaciones, gracias a ti ahora conozco algo de lo que no tenía ni idea