---
title: "gRPC vs REST: Web Menu vs Phone-Line Contract (and When to Use Which)"
description: "REST and gRPC are two ways to build an API. REST is ordering à la carte off a web menu — a plain HTTP request to a resource, JSON back, anyone can call it. gRPC is a dedicated phone line with a strict contract — a Protobuf schema, generated typed stubs, compact binary over HTTP/2 with streaming. Here's how they actually differ on speed, payload, reach, and tooling — with code — and a clear rule for which to reach for."
keywords: "gRPC vs REST, REST API, gRPC, protobuf, HTTP/2, API design, microservices API, grpc-web, streaming API, REST vs gRPC performance, when to use gRPC, protocol buffers, binary vs JSON, API gateway, backend system design"
created_at: "2026-06-26T15:00:00"
post_type: "anonym_post"
content_type: "technical_article"
---

![Banner](./banner.webp)

<div style="display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; padding: 1rem 1.25rem; margin: 1.5rem 0 2rem; background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); border: 1px solid #e2e8f0; border-radius: 12px;">
  <span style="font-size: 0.95rem; font-weight: 600; color: #475569; margin-right: 0.25rem;">Prefer to watch?</span>
  <a href="https://youtu.be/FcFliJLzh9c" target="_blank" rel="noopener noreferrer" style="display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.55rem 1rem; border-radius: 8px; background: #ff0000; color: #ffffff; font-size: 0.875rem; font-weight: 600; text-decoration: none;">▶ The full 7-minute episode</a>
  <a href="https://youtube.com/shorts/nO-WwkbImhw" target="_blank" rel="noopener noreferrer" style="display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.55rem 1rem; border-radius: 8px; background: #0f172a; color: #ffffff; font-size: 0.875rem; font-weight: 600; text-decoration: none;">⚡ The 90-second version</a>
  <a href="https://t.me/SoftwareEngineerBlog" target="_blank" rel="noopener noreferrer" style="display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.55rem 1rem; border-radius: 8px; background: #229ed9; color: #ffffff; font-size: 0.875rem; font-weight: 600; text-decoration: none;">✈ Telegram</a>
</div>

Two services need to talk. You reach for an API — and immediately hit the first real decision: **REST or gRPC?** Pick wrong and you pay for it later in either latency or developer friction. The good news: once you see what each one actually *is*, the choice is usually obvious.

The one-line mental model:

- **REST** is ordering **à la carte off a web menu** — you send a plain HTTP request to a resource, you get JSON back. Anyone can read the menu and order.
- **gRPC** is a **dedicated phone line with a strict contract** — both sides agree on a schema up front, you call typed methods, and compact binary flies over the wire.

---

## REST: order à la carte over HTTP

REST treats everything as a **resource** addressed by a URL, manipulated with HTTP verbs (`GET`, `POST`, `PUT`, `DELETE`). The payload is almost always JSON. There's no contract to share ahead of time — the "menu" is just the URLs, and any client that speaks HTTP can order.

```http
GET /orders/42 HTTP/1.1
Host: api.shop.dev
Accept: application/json

200 OK
{
  "id": 42,
  "item": "flat white",
  "status": "ready"
}
```

That's the whole appeal: it's **readable, universal, and zero-setup**. A browser, `curl`, a mobile app, a partner's backend — they can all hit it without generating any code. And because `GET`s are plain HTTP, they're **cacheable** by browsers, CDNs, and proxies for free.

---

## gRPC: a strict contract on a fast line

gRPC flips the model. Instead of loose URLs and JSON, you **define the contract first** in a Protobuf (`.proto`) schema — the methods, the request types, the response types:

```protobuf
syntax = "proto3";

service Orders {
  rpc Get(OrderId) returns (Order);
}

message OrderId { int32 id = 1; }
message Order {
  int32  id     = 1;
  string item   = 2;
  string status = 3;
}
```

You run that schema through the gRPC compiler and it **generates typed client and server stubs** for your language. Calling a remote method then looks like calling a local function:

```python
# client — the stub is generated from the .proto
import grpc, orders_pb2, orders_pb2_grpc

with grpc.insecure_channel("api.shop.dev:50051") as channel:
    stub = orders_pb2_grpc.OrdersStub(channel)
    order = stub.Get(orders_pb2.OrderId(id=42))   # typed call, binary on the wire
    print(order.item, order.status)
```

On the wire it's **compact binary over HTTP/2** — multiplexed, header-compressed, and with native support for **streaming** in either direction (server-stream, client-stream, or bidirectional).

---

## The real differences

### Speed & payload
REST ships **text JSON over HTTP/1.1**, one request/response at a time. gRPC ships **small binary (Protobuf) over HTTP/2**, multiplexed, with real streaming. For chatty, internal service-to-service traffic, gRPC is **noticeably faster and lighter** — smaller messages, fewer connections, no JSON parse on the hot path.

### Reach & tooling
This is where REST wins. REST **runs anywhere** — no shared contract, no code generation, and browsers call it directly. gRPC needs the **`.proto`, generated stubs, and HTTP/2**, and a **browser can't call gRPC directly** — you need a [grpc-web](https://github.com/grpc/grpc-web) proxy (e.g. Envoy) in front. That setup cost buys you speed and type-safety, but it's a real cost.

<table>
  <thead><tr><th></th><th>REST</th><th>gRPC</th></tr></thead>
  <tbody>
    <tr><td>Payload</td><td>JSON (text)</td><td>Protobuf (binary)</td></tr>
    <tr><td>Transport</td><td>HTTP/1.1</td><td>HTTP/2 (multiplexed)</td></tr>
    <tr><td>Contract</td><td>None required</td><td>`.proto`, generated stubs</td></tr>
    <tr><td>Streaming</td><td>Limited</td><td>First-class, bidirectional</td></tr>
    <tr><td>Browser</td><td>Direct</td><td>Needs grpc-web proxy</td></tr>
    <tr><td>Caching</td><td>Free (HTTP)</td><td>Manual</td></tr>
    <tr><td>Human-readable</td><td>Yes</td><td>No (binary)</td></tr>
  </tbody>
</table>

---

## Which should you reach for?

- **Reach for REST** when you're building a **public API**, serving **browser clients**, want **simplicity**, or benefit from **HTTP caching**. It's the right default for anything external or anything you want others to consume with zero onboarding.
- **Reach for gRPC** when it's **internal microservice-to-microservice** traffic, you need **low latency**, you want **streaming**, or you want **strict typed contracts shared across many languages**.

And the part most "vs" arguments miss: **most real systems use both.** REST (or GraphQL) at the edge for browsers and partners; gRPC between your internal services where speed and contracts matter. It's not a religious war — it's picking the right tool for each hop.

> Want the 90-second visual version? [Watch the reel.](https://youtube.com/shorts/nO-WwkbImhw)
