
Stop Guessing: 6 API Architecture Styles (Plus the Combos You’ll Actually Ship)
Most long-term API pain traces back to a decision you make early, when everything still looks clean in Postman.
Then reality shows up:
- web becomes mobile becomes partner,
- “simple CRUD” turns into complex screens,
- product wants real-time,
- devices start phoning home,
- and suddenly your “one API style” decision is six different interaction problems in a trench coat.
This post covers six core API architecture styles—REST, gRPC, WebSockets, GraphQL, SOAP, MQTT—and then goes deep on the piece most decision maps skip:
Combination architecture (how to combine styles without building a spaghetti gateway).
Quick decision map (for the impatient)
- Public APIs + cacheability + simplicity: REST
- Service-to-service + performance + typed contracts: gRPC
- Real-time bidirectional interaction: WebSockets
- Complex UI data shapes + many clients: GraphQL
- Enterprise legacy + WS- requirements:* SOAP
- IoT + unreliable networks + pub/sub: MQTT
If you need more than one bullet: that’s not a failure. That’s the job.
The 6 core API architecture styles
1) REST (Resource-based HTTP)
REST is the default because it’s readable, inspectable, and boring in the best way:
- resources addressed by URLs
- verbs as operations (GET/POST/PUT/DELETE)
- JSON over stateless request/response
Where it wins: public APIs, CRUD systems, teams optimizing for operability. What hurts later: over/under-fetching, round trips, endpoint sprawl, versioning complexity.
2) gRPC (Contract-first RPC over HTTP/2)
gRPC is built for internal reliability and performance:
- Protobuf contracts
- codegen clients + server stubs
- HTTP/2 with unary + streaming
Where it wins: microservices, low-latency systems, polyglot backends. What hurts later: browser friction, harder inspection, schema coupling discipline required.
3) WebSockets (Persistent real-time channel)
WebSockets are for interactive real-time:
- persistent connection
- full duplex messaging
- server push without polling
Where it wins: chat, collaboration, dashboards, live presence. What hurts later: connection management, scaling, security/debugging complexity.
4) GraphQL (Client-shaped data via typed schema)
GraphQL is for UI-driven data needs:
- clients request exactly the fields they need
- schema defines types and relationships
- resolvers fetch from multiple sources
Where it wins: complex UIs, multiple clients, rapid iteration. What hurts later: ops/caching complexity, query abuse risk, performance guardrails needed.
5) SOAP (Enterprise XML + WSDL)
SOAP persists in enterprise ecosystems:
- XML envelopes
- WSDL contracts
- WS-* standards (security, reliability, transactions)
Where it wins: legacy enterprise integrations, strict WS-* environments. What hurts later: verbosity, complexity, tight coupling.
6) MQTT (Pub/Sub for IoT and unreliable networks)
MQTT is lightweight messaging:
- broker-based pub/sub
- topics
- QoS delivery levels
Where it wins: IoT telemetry, constrained devices, unreliable connectivity. What hurts later: broker as critical dependency, QoS overhead.
Other API architectures worth knowing (because they often solve the combo problem)
- Event-driven APIs (Kafka/NATS/Pulsar + AsyncAPI)
- Server-Sent Events (SSE) for one-way real-time streams over HTTP
- Webhooks for external integrations and event delivery
- BFF (Backend for Frontend) to simplify UI payloads
- CQRS for splitting read and write models
How to solve combination API architecture problems
When your decision map says “REST” but product says “real-time,” you don’t rip out REST. You compose.
Think in interaction shapes:
- Commands (writes): create/update/delete
- Queries (reads): fetch state
- Events (changes): notify subscribers
Pick the best mechanism for each:
- Commands/Queries: REST (or gRPC internal)
- Events: WebSockets, SSE, MQTT, event streams, webhooks
Then glue them together with:
- a gateway for auth/routing
- a message bus for fan-out/durability
- the outbox pattern for “DB write + event publish” correctness
Combos you’ll actually ship (with deeper detail + diagrams)
Below are the combinations that show up in real systems, how they’re wired, what they’re good at, and what to watch.
1) REST + WebSockets (real-time UI + normal APIs)
Use when: interactive apps where users act and expect immediate updates (chat, collaboration, trading screens).
How it works
- REST handles “authoritative” operations: login, CRUD, payments, config.
- WebSockets handle event delivery: new messages, presence, live updates.
- Clients maintain local state and apply patches from WS events.
Common flow
- Client performs REST write (POST /messages)
- Server commits to DB
- Server publishes event to bus
- WS gateway broadcasts to subscribed clients
Guardrails
- Reconnect strategy + missed event recovery (client resync via REST GET)
- Message ordering and idempotency
- Auth token refresh over long-lived connections
2) REST + SSE (live updates, simpler than WebSockets)
Use when: the server pushes updates, but clients don’t need to send arbitrary messages back (status feeds, notifications, logs, progress updates).
How it works
- REST for normal reads/writes
- SSE endpoint for streaming updates over HTTP (
/events) - Browser-native support, simpler infrastructure than WS
Guardrails
- backpressure (slow clients)
- event replay/resume (Last-Event-ID)
- load balancer timeouts for long-held HTTP connections
3) REST + Webhooks (external real-time for partners)
Use when: you need to notify external systems reliably (payments, subscriptions, workflow triggers).
How it works
- REST for partner configuration (create webhook endpoint, rotate secrets)
- Webhooks for event delivery with retries and signing
Guardrails
- signature verification + replay protection
- retries + idempotency keys
- event versioning (don’t break partners)
4) REST + gRPC (REST outside, gRPC inside)
Use when: public integrations need HTTP/JSON, but internal services need performance and strong contracts.
How it works
- External clients hit REST gateway
- Gateway translates REST ↔ gRPC to internal services
- Internal traffic stays typed and efficient
Guardrails
- keep edge REST stable even if internal services evolve
- version protobuf carefully
- observability across translation boundaries
5) GraphQL + REST (GraphQL as aggregation layer)
Use when: UI needs flexible payloads and your backend is multiple REST services.
How it works
- Client queries GraphQL
- Resolvers call REST endpoints or databases
- Use batching (DataLoader) to avoid N+1 storms
Guardrails
- query cost limits + persisted queries
- caching strategy per resolver
- schema governance (avoid becoming a dumping ground)
6) GraphQL + WebSockets (subscriptions for live UI)
Use when: you want GraphQL’s query flexibility plus real-time updates.
How it works
- Queries/mutations over HTTP
- Subscriptions over WebSockets
- Events from bus → subscription resolver → client updates
Guardrails
- subscription scaling (many clients)
- per-tenant auth on subscription streams
- query abuse protection still applies
7) REST + MQTT (IoT telemetry + management APIs)
Use when: devices need lightweight pub/sub, but humans need normal APIs.
How it works
- MQTT for device telemetry/events/commands
- REST for provisioning, auth, config, dashboards
- Bridge MQTT → stream/storage → analytics/UI
Guardrails
- device identity + cert rotation
- topic authorization (don’t let devices publish everywhere)
- handling intermittent connectivity + retained messages
8) WebSockets + Event Bus (scaling real-time correctly)
Use when: real-time needs to scale beyond a single app instance.
How it works
- App services publish events to Kafka/NATS/Redis PubSub
- WS gateway subscribes and broadcasts
- Event bus decouples producers from connection layer
Guardrails
- presence tracking
- fan-out efficiency and backpressure
- ordering guarantees per topic/room/user
9) SOAP + REST (modernize without breaking legacy)
Use when: legacy enterprise integration is SOAP, but new clients demand REST.
How it works
- SOAP adapter translates to internal REST/gRPC services
- Keep SOAP at the edge, don’t let it infect new service design
Guardrails
- contract mapping and error translation
- careful versioning on SOAP side
- monitoring for transformation failures
The simple combo rule (stick this on a wall)
- Need real-time UI? → REST + (SSE or WebSockets)
- Need public + internal performance? → REST outside, gRPC inside
- Need UI flexibility? → GraphQL over REST/gRPC + optional subscriptions
- Need IoT? → MQTT + REST
- Need enterprise legacy? → SOAP adapter + modern internals
Wrap-up
There’s no “best API style.” There’s only best-for-your-constraints.
The mistake is trying to force one architecture style to solve every interaction shape. The win is designing a portfolio: REST or gRPC for commands/queries, plus the right event delivery mechanism (WS/SSE/webhooks/MQTT/streams) for change.
That’s how you avoid the slow-burn API regret.





