Skip to main contentSkip to user menuSkip to navigation

API Paradigms

Compare API paradigms: REST, GraphQL, gRPC, and WebSocket for different use cases.

30 min readIntermediate
Not Started
Loading...

What are API paradigms?

An API paradigm is a set of conventions for expressing operations, data, interaction direction, state, errors, and evolution between software components. REST models HTTP resources, GraphQL exposes a typed query graph, gRPC defines typed remote procedures, webhooks push asynchronous notifications, and SSE or WebSocket maintain live streams.

The choice matters because it shapes client coupling, caching, tooling, query cost, connection state, delivery semantics, failure recovery, and compatibility. No paradigm is universally faster or simpler; the workload and operating contract decide whether its strengths are useful.

The invariant to remember

Every accepted interaction must have one defined meaning through success, timeout, retry, cancellation, version change, and recovery. Transport delivery is not the same as a durable business outcome.

Review communication patterns first if request-response, asynchronous messaging, and streaming are unfamiliar.

Choose an interaction shape before a protocol

One bounded result

Request-response

The client sends an operation and waits under a deadline for success or a typed failure. REST, GraphQL, SOAP, and unary gRPC commonly use this shape.

Provider pushes later

Asynchronous notification

The producer delivers an event after a durable change. Webhooks and message-backed APIs need retry, deduplication, ordering, and replay rules.

Many responses

Server stream

The server emits ordered updates to one request or subscription. SSE and gRPC server streams fit one-way live delivery with explicit cancellation and resume behavior.

Both sides send

Bidirectional session

A long-lived connection carries messages in both directions. WebSocket and bidirectional gRPC need connection identity, backpressure, heartbeats, drain, and recovery.

API contract fit lab

Choose the interaction contract before the protocol

Select a workload, compare paradigms, and change required capabilities. The goal is a defensible contract, not a universal protocol ranking.

Workload
Paradigm

Contract verdict

The paradigm matches the selected workload contract

Now specify identity, authorization, deadlines, errors, retries, versioning, observability, and overload behavior before choosing a framework.

Semantics

Define operation identity, ordering, consistency, idempotency, errors, cancellation, and completion before transport details.

Envelope

Bound payload, query cost, stream duration, fan-out, concurrency, retries, deadlines, and per-tenant resource use.

Evolution

Version schemas and behavior additively, test old clients, publish deprecation evidence, and keep rollback compatibility.

Use HTTP resource semantics deliberately with REST

REST-oriented APIs expose resources through stable identifiers and standard HTTP semantics. The useful design surface is larger than JSON over POST.

  1. 1

    URI

    Identify the resource

    Use a stable resource identity that does not leak a temporary storage layout or implementation call stack.

  2. 2

    Operation

    Choose method semantics

    Use safe and idempotent methods accurately; define conditional updates and repeated-write behavior for mutations.

  3. 3

    Response

    Return HTTP evidence

    Use status, representation, validators, cache controls, pagination, rate-limit information, and typed error bodies consistently.

  4. 4

    Infrastructure

    Let intermediaries help

    CDNs, browsers, proxies, gateways, and observability tools can use standard headers only when the API preserves their meaning.

Make cache identity complete

  • Include authorization and representation dimensions that change the response.
  • Use Cache-Control, validators, and Vary consistently across origin and intermediaries.
  • Do not cache personalized data under a shared key.
  • Define invalidation and staleness in product terms, not only TTL duration.

Govern GraphQL as a query execution system

GraphQL lets clients select fields through a typed schema, which is valuable when clients need different connected views. That flexibility moves complexity into schema design, resolver execution, authorization, caching, and query governance.

depth

Traversal bound

Limit nested selection depth and recursive relationships before execution.

cost

Resource budget

Assign realistic cost to fields, cardinality, arguments, and fan-out rather than counting fields equally.

batch

Resolver access

Batch and cache per-request data loading to avoid N+1 calls and duplicate downstream work.

field

Authorization

Authorize object and field access using the caller, tenant, arguments, and parent context.

Persisted operations can reduce arbitrary query exposure and improve operational visibility. They do not remove the need to validate variables, authorize fields, and control resolver cost.

Use gRPC for typed service contracts, not magic performance

gRPC uses Protocol Buffers to define service methods and messages, then generates clients and servers. It supports unary, server-streaming, client-streaming, and bidirectional-streaming calls over HTTP/2.

One request produces one response. Propagate deadlines and cancellation, classify retryable status, and use operation IDs for state changes.

Generated types improve wire compatibility but do not define authorization, business validation, idempotency, or safe retries.

Push durable events through webhooks

A webhook provider calls a consumer-owned HTTP endpoint after an event. Providers should expect timeouts, retries, slow consumers, rotated credentials, and endpoints that disappear.

Webhook delivery is an asynchronous workflow

A `2xx` acknowledgement means the consumer accepted delivery under the documented contract; it does not automatically prove every downstream action completed.

Durable source

Event outbox

Records a stable event ID, type, resource version, occurrence time, and tenant after the business transaction commits.

Signed attempt

Delivery worker

Signs the exact payload and timestamp, applies endpoint policy, sends under a deadline, and records the attempt outcome.

Verify and deduplicate

Consumer inbox

Authenticates the signature, checks replay age, claims the event ID durably, validates schema, and acknowledges promptly.

Bounded recovery

Retry and quarantine

Retries transient failures with backoff and jitter, disables broken endpoints by policy, and exposes replay ownership.

Pick the simplest live transport that fits

Server to browser

SSE

Use when the browser only receives text events. Define event IDs, retention, retry hints, heartbeats, proxy timeouts, and snapshot recovery.

Full duplex

WebSocket

Use when both sides need low-latency messages. Define a versioned subprotocol, admission, per-client queues, backpressure, drain, and reconnect.

Typed services

gRPC stream

Use between compatible clients and services that benefit from generated streaming contracts and HTTP/2 flow control.

Bounded fallback

Polling

Use when update frequency is low or network infrastructure makes long-lived connections unreliable. Conditional requests can reduce unnecessary transfer.

Design the failure contract independently of transport

The same timeout can mean the server never received the request, rejected it, committed it but lost the response, or is still working. Retrying without stable operation identity can repeat a state change on REST, GraphQL, gRPC, SOAP, or a socket protocol alike.

Loading failure lab

Preparing API incidents...

Validate identity, version, and deadline before work

Evolve schemas and behavior compatibly

Wire compatibility is necessary but not sufficient. A field can remain syntactically valid while its meaning, units, default, authorization, or lifecycle changes incompatibly.

  1. 1

    Schema

    Add, do not repurpose

    Add optional fields or new enum handling. Never reuse an old field number, name, or value for a different meaning.

  2. 2

    Migration

    Read old and new

    Deploy consumers that tolerate both shapes before producers emit the new form broadly.

  3. 3

    Evidence

    Measure active consumers

    Track client and schema versions, unknown fields, deprecated operations, and compatibility failures by owner.

  4. 4

    Lifecycle

    Retire with a plan

    Publish timelines, contact owners, provide migration tooling, test rollback, and remove old behavior only after evidence confirms safety.

Let an old consumer ignore a new optional event field

Apply the shared production envelope

Every paradigm needs the same foundational controls, even when the framework names them differently.

Who may do what

Identity and policy

Authenticate clients and services, authorize every resource or field, bind tenant context, and prevent confused-deputy delegation.

Protect the service

Resource bounds

Limit payload, query complexity, stream duration, concurrency, fan-out, rate, retries, buffers, and downstream work per identity.

Make failure actionable

Typed outcomes

Distinguish validation, authorization, conflict, quota, dependency, timeout, cancellation, unknown outcome, and internal failure.

Operate

End-to-end evidence

Propagate trace and operation IDs; record route, schema, client, retries, queueing, upstream time, result, and business outcome.

Review the production checklist

Build these controls

  • Define interaction direction, operation identity, ordering, completion, and failure semantics first.
  • Use deadlines, cancellation, bounded retries, idempotency, backpressure, and admission consistently.
  • Version wire shape and meaning additively; test old and new consumers during rollout.
  • Authenticate and authorize at the resource, method, field, event, and connection boundaries that matter.
  • Measure end-to-end latency, queueing, query cost, errors, retries, saturation, and business outcomes.
  • Test lost responses, duplicate delivery, slow consumers, reconnect gaps, breaking producers, and rollback.

Avoid these traps

  • Selecting a paradigm from invented universal latency or throughput rankings.
  • Retrying state-changing operations because the transport call timed out.
  • Treating generated types as business validation or authorization.
  • Exposing unrestricted GraphQL queries, unbounded streams, or infinite webhook retries.
  • Changing field meaning in place or retiring behavior without active-client evidence.
No quiz questions available
Could not load questions file
Spotted an issue or have a better explanation? This page is open source.Edit on GitHub·Suggest an improvement