Skip to content

REST vs. Alternative API Architectures

This AEP examines REST alongside alternative API styles and explains why our organization chooses REST as the default for public and most internal HTTP APIs. It provides a pragmatic comparison, acknowledges REST’s limitations, and documents when exceptions (GraphQL, gRPC, event-driven) are appropriate.

  • JSON REST over HTTP is our default API style for external-facing and most internal integrations.
  • We allow targeted exceptions:
    • GraphQL for client-driven aggregation across many bounded contexts when REST causes persistent over/under-fetching and schema churn. In our org, GraphQL is primarily used as a Backend-for-Frontend (BFF): FE → GraphQL BFF → JSON REST APIs.
    • gRPC for low-latency, strongly-typed service-to-service calls inside trusted networks, especially when streaming is required.
    • Event-driven (pub/sub, streams) for asynchronous workflows and decoupled propagation of state changes.
  • Teams proposing alternatives must document benefits, costs, and mitigation plans and obtain approval per our Architecture Review process.

Architecture comparison matrix (practical trade-offs)

Section titled “Architecture comparison matrix (practical trade-offs)”

The following summarizes typical characteristics. Real implementations may vary; treat this as guidance, not dogma.

CriterionREST (HTTP)GraphQLgRPCJSON-RPC/HTTP RPC
Transport/ProtocolHTTP/1.1, HTTP/2, HTTP/3HTTP over single endpointHTTP/2 by defaultHTTP (varies)
Interface ModelResource/representationTyped schema & query languageIDL (proto) RPCAd-hoc RPC
CachingNative via HTTP cache, ETag, Cache-ControlHarder at intermediaries; client cachesTypically app-level onlyNone by default
Data FetchingFixed server-driven shapes; multiple endpointsClient-driven selection; single endpointServer-defined methods/messagesServer-defined methods
VersioningAdditive evolution friendly; URLs/media typesSchema evolution via deprecationProto evolution tools; new methodsAd-hoc, often brittle
StreamingSSE/WebSocket/HTTP streaming; Webhooks for push notificationsSubscriptions (server push)Native streams (bi/uni)Not typical
TypingJSON by default; multiple media types via content negotiation (documented with OpenAPI/JSON Schema)Strong schema (SDL)Strong (proto)Weak
ToolingUbiquitous; browsers, CDNs, gatewaysGood client tooling; schema-firstExcellent codegen; perfMinimal
ObservabilityEasy: status codes, headers, logsOK but single endpoint complicatesGreat inside mesh; needs interceptorsMinimal
External AdoptionVery highGrowing for public APIsMostly internal microservicesLow
Browser-friendlinessExcellentGood (same-origin/CORS)Poor (no browser)Good
PerformanceGood; benefits from caches/CDNGood; risk of N+1 server issuesExcellent latency/binaryVaries
ComplexityLow–moderateModerate–high (gateway + resolvers)Moderate–high (IDL, infra)Low
  • REST
    • Public/external APIs where interoperability, simplicity, and cacheable GETs matter.
    • Cross-team contracts that need stable URIs, standard semantics, and broad tooling.
    • Content distribution scenarios leveraging CDNs and HTTP caching.
  • GraphQL
    • Product UIs/mobile needing flexible, client-driven data shapes across many backends.
    • Reducing over/under-fetching when REST endpoints would proliferate or churn.
    • Schema-first product iteration where a gateway can encapsulate backend changes.
  • gRPC
    • Low-latency, high-throughput internal service-to-service calls in a trusted network.
    • Bidirectional streaming, flow control, and strong typing with code generation.
    • Polyglot microservices within a service mesh.
  • JSON-RPC / HTTP RPC
    • Simple internal tools and automations where resource modeling adds little value.
    • Point-to-point calls without need for intermediaries or caching.
  • Interoperability first: We integrate with external partners, vendors, and diverse client platforms. REST over HTTP is the broadest common denominator.
  • Maintainability at scale: Uniform semantics (methods, status codes, headers) reduce cognitive load across many teams.
  • Operability and observability: HTTP is transparent; gateways, proxies, CDNs, and logs speak it natively.
  • Risk management: REST’s simplicity lowers the blast radius of design errors and eases onboarding.
  • Ubiquity: Most engineers and tools (browsers, curl, OpenAPI, etc.) work out of the box.
  • Learnability: Resource-oriented modeling and standard methods are easy to teach and review consistently.
  • Documentation and discovery: OpenAPI/JSON Schema enable contract-first or code-first workflows, client generation, and validation. OpenAPI also lets us document multiple content types per operation (e.g., JSON for requests, multipart/form-data for uploads, application/octet-stream for downloads), making non-JSON use cases first-class while keeping JSON as default.
  • Gateways and proxies: Off-the-shelf support for authN/Z, rate limiting, routing, mTLS, and WAF.
  • Caching layers and CDNs: Native leverage of Cache-Control, ETag, and conditional requests.
  • Security: Mature patterns for OAuth2/OIDC, TLS termination, and zero-trust networking.
  • Observability: Standardized metrics (latency per method), logs, traces with clear operation names (method + URI).
  • For most business workloads, REST performance is sufficient, especially when leveraging caching and proper resource design.
  • Alternatives often introduce new infra (schema registries, gateways, meshes) and specialized skills; we adopt them only when the measurable benefit exceeds this complexity.
  • GraphQL gateway in front of existing REST/gRPC when product teams need client-driven aggregation.
  • gRPC for internal microservice calls that are latency-sensitive or require streaming.
  • Event-driven integrations for async workflows, backpressure, and decoupled propagation.

All exceptions require an ADR (Architecture Decision Record) that includes:

  • Specific problems REST cannot solve for your use case
  • Quantified benefits (performance, developer productivity, etc.)
  • Infrastructure and operational costs
  • Team expertise and learning curve
  • Migration/rollback plan if needed

REST limitations and mitigation strategies

Section titled “REST limitations and mitigation strategies”
  • Problem: Fixed representations cause clients to request more or fewer fields than needed.
  • Mitigations:
    • Projection parameters (e.g., fields=...) with bounded, documented fields.
    • Embedded/expand parameters for related resources (e.g., ?expand=items,payments).
    • Backend-for-Frontend (BFF) or aggregator endpoints where appropriate.
  • Problem: Evolving contracts without breaking existing clients.
  • Mitigations:
    • Prefer additive, backward-compatible changes; avoid breaking renames.
    • Deprecation policy with timelines and communication expectations.
    • Versioning strategy per org policy (URI/header/media-type) and migration playbooks.
  • Problem: Rich filtering, sorting, search, and analytics via query parameters can become unwieldy.
  • Mitigations:
    • Consistent filtering/sorting conventions; pagination standards.
    • Dedicated search resources that accept structured bodies for complex queries.
    • Offload analytics to data services; avoid turning REST into adhoc query language.
  • Problem: Clients need live updates or server-initiated messages.
  • Mitigations:
    • Server-Sent Events (SSE) for unidirectional server → client streams over HTTP using the text/event-stream media type.
    • WebSockets for bidirectional, low-latency messaging when clients must also push events.
    • Webhooks for event notifications with follow-up GETs when clients can receive callbacks.
    • Prefer SSE for broadcast/append-only event feeds where HTTP semantics and intermediaries are beneficial; use WebSockets when client-to-server push or complex realtime patterns are required.
  • Problem: JSON alone lacks strong typing and codegen ergonomics.
  • Mitigations:
    • OpenAPI + JSON Schema for validation and client generation.
    • Contract tests and schema linting in CI.
  • Problem: Inefficient transfer of large media or binary data.
  • Mitigations:
    • Use multipart/form-data for file uploads when clients need to send files alongside JSON fields (e.g., metadata). Document field names, size limits, and validations.
    • Serve downloads as application/octet-stream (or a specific media type) and include Content-Disposition for filenames. Support Range Requests (HTTP 206) for efficient resume/seek.
    • Pre-signed URLs to object storage for direct upload/download paths to keep application nodes stateless and avoid buffering large bodies.
    • Consider resumable/multipart upload protocols when needed.
    • Content negotiation and compression where appropriate.
    • Provide integrity checks (e.g., checksum metadata or the HTTP Digest header where supported).
  • 2025-10-31: Initial creation.