skip to content

When designing one API surface, how do action-oriented RPC, resource-oriented REST and query-oriented GraphQL differ in what the interface is built around?

level: juniorimportance: must knowfreq 42%

answer

  1. what is the organising noun
  2. verbs, nouns, or a graph
  3. named procedures vs fixed HTTP methods
  4. client picks the fields

basics

~20 s

RPC exposes named procedures the client calls with arguments; REST exposes addressable resources handled through HTTP's fixed methods; GraphQL exposes one typed graph the client queries for exactly the fields it wants. That organising choice drives caching, coupling and tooling.

solid answer

~40 s

The three styles differ in what the interface is made of. An **RPC** API is a list of named procedures - `CancelOrder`, `GetQuote` - each with its own arguments and result, so the vocabulary grows with every operation and a client usually calls through a generated stub. A **REST** API is a set of addressable resources (`/orders/8812`) manipulated through HTTP's small, fixed set of methods, so the domain lives in URLs and representations and HTTP semantics (safe `GET`, status codes, caching) apply to every call. A **GraphQL** API is one typed schema behind a single endpoint; the client writes a query or mutation selecting exactly the fields it needs. In practice: RPC fits action-heavy internal contracts, REST fits broad public reach and HTTP caching, GraphQL fits clients that compose varied views from one graph.

go deeper

for a junior

Name the unit each style is built around - procedures, resources, a typed graph - and give one example call in each style for the same operation.

for a middle

Explain what each style lets HTTP see: a safe GET on a URL versus a POST that hides whether it reads or writes, and what that means for caches and tooling.

for a senior

Tie the organising idea to consequences you have lived with: stub coupling across teams, caching lost behind POST, and the server cost of client-chosen GraphQL queries.

for a principal

Frame the styles as fits for different consumers, and argue where one surface deserves a second face instead of forcing every client through one style.

## The organising idea of each style Every API style answers one question first: **what is the unit a client talks to?** The answer shapes everything downstream. | | RPC | REST | GraphQL | |---|---|---|---| | Unit of the interface | a named **procedure** | an addressable **resource** | one typed **graph** | | Where the operation is named | the method name (`CancelOrder`) | the HTTP method on a URL (`GET /orders/8812`) | the operation and its field selection | | Vocabulary size | grows with every operation | fixed methods, growing set of resources | fixed operation types, growing schema | | Typical endpoint shape | one endpoint, or one path per method | one URL per resource | one endpoint for everything | | Who decides the response shape | the server, per method | the server, per representation | the client, per query | - **RPC (remote procedure call)** makes a remote operation look like a function call: the client calls `CancelOrder(orderId, reason)` and gets a result or an error. Named systems from ONC RPC to gRPC and JSON-RPC 2.0 follow this shape. - **REST** models the domain as resources identified by URLs and uses HTTP's uniform interface - `GET`, `PUT`, `POST`, `DELETE`, `PATCH` - with their defined meanings (RFC 9110 calls `GET` safe and `PUT` and `DELETE` idempotent). - **GraphQL** publishes a schema of types and fields; a client sends a **query** (read), **mutation** (write) or **subscription** (stream) document naming exactly the fields it wants back. ## What the client has to know 1. **RPC client:** the list of procedures, their argument and result types, and the error codes each can return. That knowledge usually arrives as generated code from an interface definition, so a client is coupled to method names and signatures. 2. **REST client:** the resource URLs (or how to discover them from links), the representation formats, and HTTP itself. A generic HTTP client, a browser or a cache already understands the method and status-code semantics. 3. **GraphQL client:** the schema. Because the client chooses its fields, adding a field never changes what an existing query receives; the price is that the server must be ready for any combination of fields a client might ask for. ## What HTTP and its intermediaries can see - A REST `GET /orders/8812` tells every proxy and cache what it is: a safe read of one URL, whose response RFC 9110 makes cacheable. - An RPC call carried over HTTP is usually a `POST` (gRPC defines every call as `:method POST`), with the operation named in the path or the body; intermediaries cannot tell a read from a write. - A GraphQL request is typically a `POST` of a query document to one URL, so a shared cache sees the same URL for every question. That is why **HTTP caching and visibility** favour resource style, while RPC and GraphQL move caching into the client or the application. ## Contract and code generation All three can be contract-first. RPC systems lean hardest on it: an interface definition generates client stubs and server skeletons, which gives type safety and fast calls but couples both sides to the same definition. REST APIs are described separately (an OpenAPI document) and work fine without generated code. GraphQL's schema is both contract and query language, and clients often generate types from their own queries. ## Where messaging fits None of the three removes the wait: the caller sends a request and the outcome comes back in the same exchange. **Messaging** - publishing a command or event to a broker - is the fourth option, chosen when the caller does not need the outcome now. It trades the immediate result for decoupling in time. ## A rule of thumb - Action-heavy, internal, performance-sensitive contracts with codegen on both sides lean **RPC**. - Public or partner surfaces that must work from any HTTP client and benefit from caching lean **REST**. - Client applications that assemble varied screens from many related entities lean **GraphQL**. None of these is a law: a REST API can carry action endpoints, an RPC framework can expose a REST face, and a GraphQL server can sit in front of RPC services. The choice is which organising idea best matches the operations and the clients.

  • Is an API that uses JSON over HTTP automatically REST?
    No. JSON over HTTP is only the encoding and the transport. If every call is a `POST` to `/api` with an action name in the body, the API is RPC-shaped: the operations are procedures, not resources, and HTTP's method semantics and caching go unused. REST is about addressable resources manipulated through the uniform interface, whatever the encoding.
  • Why does GraphQL usually need only one endpoint while REST needs many URLs?
    In GraphQL the operation is described by the query document itself - which types, which fields, which arguments - so one URL can serve every request. In REST the URL identifies the resource being acted on, so each resource needs its own address, and HTTP's method on that address says what to do.

RPC is a service desk where you name the task you want done; REST is a filing cabinet of labelled folders that everyone handles with the same few actions; GraphQL is a request slip on which you list exactly the facts you want back.

saying these in an interview costs you the question

  • Any API sending JSON over HTTP is a REST API.
  • GraphQL is a database query language that exposes the tables directly.
  • RPC cannot run over HTTP; it needs its own binary transport.
  • REST means using exactly the four CRUD methods and nothing else.
  • The three styles differ only in payload format, not in what the interface is made of.