Tag: gRPC

  • REST, gRPC, GraphQL, WebSocket — When to Choose Which

    REST, gRPC, GraphQL, WebSocket — When to Choose Which

    What we keep missing in the Architecture Review Board — and the drawbacks of each pattern


    When a new requirement lands, we open the Architecture Review Board (ARB).

    The room fills quickly. Mid-level engineers come prepared — and passionate. Someone says: “We’ll do gRPC.” Someone else: “GraphQL is better for the UI.” Another: “Just expose a REST API — everyone knows it.”Occasionally WebSockets enter the chat because “we need real-time.”

    I understand the concern. Everyone is trying to move fast and pick a modern, credible tool.

    But sometimes we miss the fundamentals between all of them.

    gRPC, GraphQL, REST, and WebSocket are not competing logos. They are different communication patterns. They answer different questions about how long the conversation lasts, who is calling, how much of the data the client needs, and what fails when the network gets ugly.

    In this article I explain when to choose which communication pattern, and — just as important — what the drawbacks of each are. The examples come from high-scale gaming and payments platforms we built: matchmaking, live tables, real-time query APIs, and service-to-service paths behind the client.

    Same ARB energy. Clearer criteria.

    What the ARB should ask before naming a protocol

    Before anyone says “gRPC” or “GraphQL,” force these questions:

    1. Is this a short request/response, or a living session?

    2. Is the caller a browser/app, a partner, or an internal service we control?

    3. Does the client need a fixed contract, a flexible read shape, or a stream of events?

    4. Are we optimizing for universality and debuggability, binary efficiency, or push latency?

    5. Who owns versioning when the contract changes?

    If you cannot answer those, you are not choosing a pattern. You are choosing a buzzword.

    REST — when to choose it

    Choose REST when the interaction is “ask and get an answer”: short-lived, resource- or command-oriented, and best served by ordinary HTTP (methods, status codes, gateways, caches).

    Matchmaking was a scalable REST service. The client called it first. The service read live tables/seats from cache, applied rules, and returned game table info (later including a sticky cookie). Only then did the client know where to play.

    The Dynamic Real-Time Query Engine exposed REST APIs so CRM, ML, and targeting could send a behavioral query and get a decision. Request/response. Wide consumer set. Spring Boot + HTTP was the interoperable door.

    Why ARB likes REST (for good reasons)

    Every platform can call it

    API gateways already know how to auth, rate-limit, and route it

    Easy to debug (`curl`, logs, status codes)

    Natural for onboarding, config, “place me,” “get segment,” partner integrations

    Drawbacks / backdrops

    Chatty UIs — one screen may need many round trips

    Over-fetching / under-fetching — one DTO rarely fits every client

    Poor fit as the primary game loop — polling REST for table state is a smell

    Versioning sprawl — `/v1` `/v2` and bloated payloads if governance is weak.

    ARB line: If the conversation ends when the response returns, REST is the default until proven otherwise.

    WebSocket — when to choose it

    Choose WebSocket when you need a persistent, bidirectional channel: server push, client push, session as long as the user is inside an experience.

    Where it fit for us

    Gameplay was never REST polls. Early on, clients held a persistent socket for the life of the session — input in, broadcast out.

    Later we moved to WebSockets behind an API gateway (auth, security, rate limits, routing).

    Flow:

    1. REST matchmaking → table info + sticky cookie

    2. WebSocket through the gateway → live game path

    3. Stay connected for the session; server fans out state

    Historically we also separated lobby vs game connections so browsing spikes did not punish a live table.

    Why ARB likes WebSocket

    True real-time without fake polling

    Efficient for many small messages after handshake

    Matches how games, live ops, and collaborative UIs actually work

    Drawbacks / backdrops

    Operational hardness — sticky sessions, reconnect storms, heartbeats, backpressure

    Gateway and LB behavior become architecture — not an afterthought

    Horizontal scale is non-trivial — affinity, failover, “who owns this gameId?”

    Abuse risk — open sockets are a DoS surface if rate limits and auth are weak

    Wrong tool for one-shot CRUD — login and “get config” do not need a socket

    ARB line: Use REST (or similar) to enter the room. Use WebSocket to live in the room.

    gRPC — when to choose it

    Choose gRPC when callers are services inside your trust boundary, you want a strict contract (Protobuf), and you care about efficiency, deadlines, and codegen. Where it fits in stacks like ours

    Client-facing traffic stayed REST + WebSocket. gRPC earns its keep service-to-service:

    High-QPS internal lookups (profile, features, decision helpers)

    Strong typing across languages

    Unary or streaming RPCs without inventing a private framing protocol

    A fraud Decision API or internal RTQE neighbor might speak gRPC internally while broader consumers still see REST.

    Why ARB likes gRPC

    Compact binary payloads; strong performance story

    Contract-first with breaking-change discipline

    Deadlines, status codes, streaming built in

    Excellent for polyglot microservices you own

    Drawbacks / backdrops

    Browsers are awkward — need grpc-web or a proxy; not “just fetch”

    Ops complexity — HTTP/2 load balancing, observability, and client libraries must be mature

    Less human-debuggable than JSON REST in a pinch

    Overkill for simple public or partner APIs

    False comfort — a `.proto` does not replace product thinking about failure modes

    ARB line: gRPC for internal contracts. Do not force it to the client because it feels advanced.

    GraphQL — when to choose it

    Choose GraphQL when many clients need different shapes of the same domain, and REST over/under-fetching is slowing product teams — and you are willing to govern a schema.

    Where it fits

    BFF / app / admin / CRM consoles: screens that would otherwise need five REST calls or one monstrous DTO.

    Where I push back hard

    Hot game loops — use WebSocket state sync, not GraphQL as the table protocol

    Simple commands — REST is clearer

    Blind “GraphQL everywhere” — schema sprawl is an enterprise debt

    Why ARB likes GraphQL

    Clients ask for exactly the fields they need

    One endpoint can serve many UI variants

    Strong story for mobile and parallel frontends

    Drawbacks / backdrops

    N+1 and resolver cost — easy to create accidental database storms

    Caching is harder than REST resource URLs

    Authz must be field-aware — coarse gateway auth is not enough

    Schema governance — without owners, GraphQL becomes a junk drawer

    Subscriptions ≠ free real-time architecture — still need backplane thinking

    ARB line: Choose GraphQL for read-shape flexibility. Do not choose it to avoid designing APIs.

    Side-by-side: pattern vs backdrop

    PatternChoose whenMain drawbacks
    RESTShort request/response; broad clients; gatewaysChatty UIs; over/under-fetch; weak as live game pipe
    WebSocketLong-lived bidirectional session; server pushSticky/reconnect complexity; harder to scale; easy to misuse for CRUD
    gRPCInternal service RPC; strict contracts; efficiencyBrowser friction; ops maturity required; overkill for public CRUD
    GraphQLMany clients, many read shapesN+1; cache/authz hardness; schema sprawl

    How we composed them (what “good” looked like)

    ConversationPattern
    Matchmaking / “where do I sit?”REST
    Live gameplay / presenceWebSocket
    CRM / ML segment queryREST (+ JSON body)
    Service-to-service, high QPS, strictgRPC (internal)
    Diverse admin / app readsGraphQL (when UI diversity demands it)
    Durable async side effects (e.g. money path)Message broker — different layer, not a fifth “API style”

    What I say in the ARB when the suggestions fly

    When someone says “we’ll do gRPC / GraphQL / REST,” I translate:

    REST — “We need a door everyone can knock on.”

    WebSocket — “We need a room that stays open and pushes.”

    gRPC — “Two services we own need a tight, fast contract.”

    GraphQL — “Many UIs need many shapes of one graph — and we will govern the schema.”

    If the sentence is only “it’s modern,” that is not an architecture decision.

    Wrapping-Up

    In the ARB, mid-level energy is valuable. Protocol fashion is not.

    Sometimes we miss the funda: REST, gRPC, GraphQL, and WebSocket solve different communication problems, and each brings drawbacks you must budget for — chattiness, connection ops, browser proxies, schema and resolver risk.

    When a new requirement opens the board, don’t start with the acronym. Start with the conversation type. Then choose the pattern. Then name the backdrops out loud so nobody is surprised in production.

    Enter with REST when you need a door.

    Stay with WebSocket when you need a room.

    Speak gRPC when services need a tight contract.

    Offer GraphQL when many UIs need many shapes — and you will own the schema.