Skip to content

gRPC Introduction — High-Performance Microservices Communication

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about grpc introduction. We cover key concepts, practical examples, and best practices to help you master this topic.

gRPC is a high-performance RPC framework using Protocol Buffers and HTTP/2 that enables strong typing, bi-directional streaming, and efficient binary serialization for microservices communication.

What You'll Learn

By the end of this lesson you will understand gRPC's architecture, write Protocol Buffer definitions, generate client and server code, compare gRPC with REST, and know when gRPC is the right choice.

Why It Matters

REST with JSON is simple but wasteful. JSON Parsing is CPU-intensive, text-based serialization is verbose, and HTTP/1.1 limits multiplexing. gRPC solves these problems with binary serialization, HTTP/2 multiplexing, and automatic Code Generation that guarantees type safety.

Real-World Use

DodaZIP's compression service uses gRPC for internal communication between the API Gateway and worker nodes. The binary protocol reduces payload size by 60% compared to JSON, and the streaming API enables real-time progress updates during file compression.

flowchart LR
    A[Client Service] -->|protobuf binary| B[gRPC Server]
    B -->|HTTP/2 multiplexed| A
    C[.proto File] -->|Code Generate| D[Client Stub]
    C -->|Code Generate| E[Server Skeleton]
    D --> A
    E --> B
    style C fill:#2d3748,color:#fff

Protocol Buffers

Define service contracts in .proto files.

# protobuf_intro.py
# Protocol Buffers definition

def protobuf_example():
    print("Protocol Buffers (.proto) Example")
    print("=" * 40)
    print()
    print('syntax = "proto3";')
    print()
    print("package user.v1;")
    print()
    print('service UserService {')
    print("  rpc GetUser (GetUserRequest) returns (User);")
    print("  rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);")
    print("}")
    print()
    print("message GetUserRequest {")
    print("  string user_id = 1;")
    print("}")
    print()
    print("message User {")
    print("  string id = 1;")
    print("  string email = 2;")
    print("  string name = 3;")
    print("  int32 age = 4;")
    print("}")
    print()
    print("Benefits:")
    print("- Strongly typed schema for all messages")
    print("- Backward compatible field evolution")
    print("- Code generation for multiple languages")
    print("- Binary format ~10x smaller than JSON")

protobuf_example()

HTTP/2 Advantages

Why HTTP/2 matters for microservices.

# http2_benefits.py
# HTTP/2 features used by gRPC

def http2_features():
    print("HTTP/2 Features Used by gRPC")
    print("=" * 40)
    print()
    
    features = [
        {
            "feature": "Multiplexing",
            "desc": "Multiple streams over single TCP connection",
            "benefit": "No head-of-line blocking, fewer connections"
        },
        {
            "feature": "Server Push",
            "desc": "Server sends resources client hasn't requested yet",
            "benefit": "Reduces round trips for related data"
        },
        {
            "feature": "Binary Framing",
            "desc": "All data transmitted in binary frames",
            "benefit": "Efficient parsing, smaller overhead"
        },
        {
            "feature": "Stream Prioritization",
            "desc": "Client can prioritize certain streams",
            "benefit": "Critical requests get bandwidth first"
        },
        {
            "feature": "Header Compression",
            "desc": "HPACK compression for HTTP headers",
            "benefit": "Reduces header overhead significantly"
        },
    ]
    
    for f in features:
        print(f"{f['feature']:25s}")
        print(f"  Description: {f['desc']}")
        print(f"  Benefit:     {f['benefit']}")
        print()

http2_features()

gRPC vs REST

A feature comparison of both protocols.

# grpc_vs_rest.py
# Detailed comparison

def compare_grpc_rest():
    print("gRPC vs REST Comparison")
    print("=" * 40)
    print()
    
    comparisons = [
        ("Protocol", "HTTP/2 (binary)", "HTTP/1.1 or HTTP/2 (text)"),
        ("Data Format", "Protocol Buffers (binary)", "JSON or XML (text)"),
        ("Contract", "Required (.proto file)", "Optional (OpenAPI)"),
        ("Streaming", "Bidirectional streaming", "Request-response only"),
        ("Code Generation", "Built-in", "Third-party tools"),
        ("Browser Support", "Limited (needs gRPC-web)", "Native support"),
        ("Payload Size", "~30% of JSON size", "Full text size"),
        ("Parsing Speed", "~10x faster than JSON", "Slower text parsing"),
        ("Human Readability", "No (binary)", "Yes (JSON text)"),
    ]
    
    print(f"{'Aspect':25s} {'gRPC':35s} {'REST':35s}")
    print("-" * 95)
    for aspect, grpc, rest in comparisons:
        print(f"{aspect:25s} {grpc:35s} {rest:35s}")

compare_grpc_rest()

When to Choose gRPC

Decision criteria for adopting gRPC.

# when_grpc.py
# Decision criteria for gRPC

def when_to_use_grpc():
    print("When to Choose gRPC")
    print("=" * 40)
    print()
    
    criteria = [
        {
            "condition": "High internal traffic between services",
            "reason": "Binary protocol reduces bandwidth and parsing overhead"
        },
        {
            "condition": "Real-time streaming requirements",
            "reason": "gRPC supports bidirectional streaming natively"
        },
        {
            "condition": "Polyglot environment (multiple languages)",
            "reason": "Code generation produces native clients in 11+ languages"
        },
        {
            "condition": "Performance-critical paths",
            "reason": "Protobuf serialization is 10x faster than JSON"
        },
        {
            "condition": "Strong contract enforcement needed",
            "reason": "Breaking changes caught at compile time, not runtime"
        },
    ]
    
    for c in criteria:
        print(f"  Condition: {c['condition']}")
        print(f"  Reason:    {c['reason']}")
        print()

when_to_use_grpc()

Common Mistakes

  1. Using gRPC for browser-facing APIs: gRPC requires gRPC-web for browser support, which adds complexity. Use REST for external APIs and gRPC for internal service-to-service communication.

  2. Ignoring field numbering in protobuf: Field numbers 1-15 use 1 byte, 16-2047 use 2 bytes. Number fields inefficiently and waste bandwidth on every message.

  3. Not handling backward compatibility: Adding required fields breaks existing clients. Use optional fields and sensible defaults for evolution.

  4. Using gRPC for small, simple services: The overhead of protobuf compilation and HTTP/2 setup is not justified for services with minimal traffic. REST is simpler for low-volume APIs.

  5. No deadline/timeout propagation: gRPC supports deadlines (timeouts) that propagate through the call chain. Without them, a slow downstream service can hold resources indefinitely.

Practice Questions

  1. What serialization format does gRPC use? Protocol Buffers (protobuf), a binary serialization format defined in .proto files.

  2. What HTTP protocol does gRPC require? HTTP/2, which provides multiplexing, binary framing, and streaming support.

  3. How is gRPC different from REST in terms of contracts? gRPC requires a .proto contract file that generates both client and server code. REST contracts are optional and typically documented in OpenAPI.

  4. What is the advantage of gRPC streaming over REST polling? Streaming provides real-time data push over a single persistent connection, while polling requires repeated HTTP requests with overhead.

  5. Challenge: Design a gRPC service for a real-time chat application. Define the .proto file with messages for SendMessage, ReceiveMessage (streaming), and typing indicators.

FAQ

Is gRPC faster than REST?

Yes, for internal service-to-service calls. Binary serialization and HTTP/2 multiplexing make gRPC significantly faster, especially for high-throughput scenarios.

Can gRPC be used in browsers?

Yes, via gRPC-web, but it has limitations. For browser clients, REST or GraphQL are often simpler.

What languages does gRPC support?

Go, Java, Python, Node.js, C++, C#, Ruby, PHP, Dart, Rust, Swift, Kotlin, and more via community implementations.

How do you handle breaking changes in protobuf?

Follow protobuf best practices: never reuse field numbers, use reserved fields for removed fields, add new fields as optional.

Does gRPC support authentication?

Yes. gRPC supports SSL/TLS for transport security and can use token-based auth (JWT, OAuth2) via interceptor middleware.

Mini Project

Define a .proto file for a file processing service that accepts a file upload request, streams progress updates during processing, and returns the final result. Generate the server and client stubs conceptually and write a client that calls the streaming API.

def file_processing_proto():
    print("File Processing gRPC Service")
    print("=" * 40)
    print()
    print('syntax = "proto3";')
    print()
    print("package fileproc.v1;")
    print()
    print('service FileProcessor {')
    print("  rpc ProcessFile (ProcessRequest) returns (stream ProgressResponse);")
    print("}")
    print()
    print("message ProcessRequest {")
    print("  string filename = 1;")
    print("  bytes content = 2;")
    print("  string compression_type = 3;")
    print("}")
    print()
    print("message ProgressResponse {")
    print("  int32 percent_complete = 1;")
    print("  string status = 2;")
    print("  string result_url = 3;")
    print("}")
    print()
    print("Usage:")
    print("  Client sends ProcessRequest once")
    print("  Server streams ProgressResponse updates")
    print("  Client shows real-time progress bar")

file_processing_proto()

What's Next

Next: gRPC Unary for implementing unary RPC calls.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro