“Is this a REST API or an RPC?”
Design reviews often treat REST and RPC as rival products. They are closer to rival vocabularies for the same problem: how should one process ask another for work over the network?
Both can ride HTTP. Both can return JSON. Both can power a mobile app. The fork is what you name and version: resources you manipulate, or procedures you call.
This post is the contract-level distinction — not a bake-off of gRPC vs Spring Boot, and not the cellular round-trip story in Fat vs Chatty APIs. Those concerns stack; they do not replace each other.
Related reading
- Internal: Fat vs Chatty APIs on Cellular — payload shape and RTT on phones
- Internal: Three Clients, Same Aggregation — where aggregation lives when clients disagree
- External: Fielding’s REST dissertation (ch. 5); gRPC docs — core concepts; Postman — gRPC vs REST
Two ways to carve the surface
REST (Representational State Transfer) is an architectural style. In the HTTP mapping most teams mean: URLs name resources, verbs (GET / POST / PUT / PATCH / DELETE) say what to do, status codes carry outcomes, and clients navigate representations. Idealized REST is more than “JSON over GET”; day-to-day “REST APIs” are usually resource-oriented HTTP.
RPC (Remote Procedure Call) names operations. The client invokes something that looks like a function: GetUser, CreateOrder, SendMessage. Classic RPC stacks (ONC RPC, CORBA, Java RMI) made that literal. Modern cousins — gRPC, JSON-RPC, many “POST /api/v1/sendMessage” endpoints — keep the procedure as the unit of design even when the wire is HTTP/2 + Protobuf or HTTP + JSON.
| Resource-oriented (REST-ish) | Procedure-oriented (RPC-ish) | |
|---|---|---|
| Unit of design | Noun / resource | Verb / method |
| Example | GET /users/42 |
GetUser(id=42) or POST /rpc/GetUser |
| Uniform interface | Shared HTTP verbs + status | Per-service method catalog |
| Typical public web/mobile edge | Common | Less common (except RPC-over-HTTP) |
| Typical service-to-service | Fine | Common (gRPC, etc.) |
| Streaming | Possible; not the default mental model | First-class in gRPC (uni/bi-directional) |
They are alternatives for how you model the contract. They are not mutually exclusive technologies: a shop can expose REST at the edge and gRPC between services, or run RPC-shaped JSON on the same API gateway that also hosts CRUD resources.
What the phone actually notices
From an Android client, the label on the wiki matters less than three practical facts.
1. Client shape. Retrofit/OkHttp against resource URLs feels natural for CRUD screens. gRPC (or a generated RPC stub) feels natural when the backend already speaks Protobuf and methods. Either way you still own timeouts, cancellation, and “what does a partial failure mean for this screen?”
2. Chatty vs fat is orthogonal. Six GETs per list row is a REST usage smell; six tiny RPCs is the same smell with different names. Aggregating for cellular (fat vs chatty) can sit behind a BFF whether the BFF’s public face is resource JSON or a GetInboxPage RPC.
3. Evolution and tooling. Resource APIs lean on HTTP caching semantics, CDN habits, and browser-friendly debugging. RPC/gRPC leans on shared schemas, codegen, and (for gRPC) binary framing that is awkward in a browser without a gateway. Public partner integrations still skew REST-ish for that reason; internal meshes often skew RPC for throughput and typing — a pattern many eng blogs describe as hybrid rather than winner-take-all (freeCodeCamp on REST / gRPC / events, Toptal on gRPC vs REST).
False fights worth skipping
“RPC is faster, so use it everywhere.” Binary Protobuf and HTTP/2 multiplexing can win on internal latency. On a phone, radio RTT and round-trip count usually dominate serialization microbenchmarks. Faster framing does not forgive a chatty screen contract.
“If it uses POST, it isn’t REST.” Plenty of resource APIs use POST for non-idempotent creates or actions. Plenty of “REST” APIs are RPC in a trench coat (POST /getUser). Judge by whether resources and uniform verbs are the organizing idea — not by whether someone pasted OpenAPI into Confluence.
“GraphQL replaces both.” GraphQL is a third vocabulary: the client shapes a query document. It is neither classic REST nor classic RPC, though it often replaces a cluster of chatty GETs the way a fat BFF method would.
When I’d reach for which
Prefer resource-oriented HTTP when many clients (including browsers and partners) need a stable, cache-friendly vocabulary over entities, and when human debuggability at the edge matters.
Prefer RPC (often gRPC internally) when both ends are under your control, you want a typed method catalog, streaming, or tight service-to-service loops — and you are willing to run codegen and a gateway where browsers or partners appear.
Prefer both when the edge must stay boring and the mesh must stay fast. Put aggregation where product screens need it (BFF); do not pretend the wire style alone fixed cellular physics.
References
- Architectural Styles and the Design of Network-based Software Architectures — Roy Fielding — REST as defined, not as marketing
- gRPC Core concepts — modern RPC framing (HTTP/2, stubs, streaming)
- gRPC vs REST (Postman) — accessible side-by-side of styles and tooling
- Service-to-service: REST, gRPC, and events (freeCodeCamp) — hybrid production pattern
- gRPC vs REST (Toptal) — performance and when complexity pays off