Skip to content

API Design and Networking

How clients and servers talk. REST, gRPC and GraphQL, HTTP basics, and when to choose TCP or UDP.

beginner35 minAsked oftenApi designRestGrpcGraphqlHttpTcpUdp

Last reviewed 24 Oct 2026 · by TheLearningLoop Team

Progress is saved on this device. Create a free account to keep it everywhere.

On this page ▾

Key takeaways

  • An API is a contract. Design it around what clients need, keep it stable, and add versions instead of breaking it.
  • REST fits public, cacheable resources. GraphQL fits clients that need flexible data in one trip. gRPC fits fast, typed calls between your own services.
  • TCP delivers every byte in order, and UDP trades guarantees for speed. Each request costs round trips, which dominate on slow networks.

Why API design matters, and how to choose

Every system is made of parts that talk to each other: a phone app and a server, one service and another. The API (application programming interface) is the agreement about how: what you can ask for, what you send, and what comes back. Once other people's code depends on it, it is hard to change, so it is one of the most important things to get right.

A good API and a good choice of protocol give you two things interviewers always ask about:

  • A clear, stable contract: clients and servers can change independently without breaking each other.
  • Efficient communication: few round trips and small payloads, so screens load fast even on slow networks.

Choose REST when:

  • The API is public or used by many different clients, and the data maps to resources (users, orders).
  • You want to use HTTP caching and simple tools.

Choose GraphQL when:

  • Clients such as mobile apps need different shapes of data and you want them to ask for exactly what they need in one trip.

Choose gRPC when:

  • Your own services call each other a lot, and you want a strict typed contract, small binary messages and streaming.

Choose something else when:

  • You need the server to push updates (chat, live scores): use WebSockets or server-sent events.
  • A single simple endpoint is all you need: a plain REST endpoint is enough. Do not add GraphQL or gRPC for the sake of it.

Try it

Start with the API styles tab: pick a style and a network, and watch how long one profile screen takes to load. Then open the TCP vs UDP tab.

Loading one profile screen

Step 1 of 5 · Press Space to play, arrow keys to step
API style:
Network:
  1. No requests yet.
  • User: not yet
  • Posts: not yet
  • Followers: not yet

Start: a profile screen needs the user's name and photo, their latest three post titles, and a follower count, about 1,100 bytes in all. The round trip to the server is 150 ms. Press play to see the requests.

round trips:
0
bytes received:
0
bytes the screen needs:
1,100
page ready (ms):
waiting
parts failed:
0

Teaching numbers, not measurements: each request costs one round trip plus 5 ms of server time, and the link moves about 1 KB per ms. The point is the shape: round trips dominate on a slow network.

Things to try:

  • REST (one call per resource) on the poor mobile network: three round trips and 8,300 bytes of data for a screen that needs about 1,100. The page is ready after 474 ms (teaching numbers).
  • Switch to GraphQL, or REST with a /profile endpoint: one round trip, so the page is ready after 157 ms. Now try the good network: the gap shrinks to 84 ms against 27 ms. Round trips hurt most when the network is slow.
  • Tick The posts service is failing. With plain REST and GraphQL, the user and follower count still show (2 of 3 parts). With a single /profile call or gRPC call that fails as a whole, the screen gets nothing. One big call is faster, and also all-or-nothing unless you design for partial results.
  • On the TCP vs UDP tab, lose packets 3 and 7. TCP resends them, delivers all 10 in order, and takes 300 ms instead of 100. UDP takes 100 ms and delivers 8 of 10, with gaps.

API styles

StyleHow it worksGood whenWeakness
REST over HTTPResources at URLs (/users/42), standard methods (GET, POST, PUT, DELETE) and status codes, usually JSONPublic APIs, simple CRUD, cacheable readsSeveral calls for one screen; over-fetching and under-fetching
GraphQLOne endpoint; the client sends a query naming the fields it wantsMany client types, nested data, mobile appsMore server complexity; caching and query cost are harder; N+1 risk
gRPCTyped methods defined in a .proto file, binary messages over HTTP/2, with streamingService-to-service calls, low latency, strict contractsNot directly usable from a plain browser; harder to read and debug
WebSockets or server-sent eventsA long-lived connection the server can send messages downChat, live updates, notificationsConnections to keep alive and scale; more stateful

TCP vs UDP

  • TCP gives you a reliable, ordered stream. It sets up a connection, numbers the data, and resends anything lost. Web pages, APIs, files and databases use it. The cost: a setup step (the handshake) and waiting when a packet is lost, which delays everything behind it (head-of-line blocking).
  • UDP sends independent packets with no setup, no resends and no ordering. It has less delay and fewer guarantees. Live video and voice, games and DNS lookups use it, where a late packet is worth less than a fresh one.

HTTP/1.1 and HTTP/2 run over TCP. HTTP/3 runs over QUIC, which is built on UDP and adds its own reliability, to avoid some of TCP's blocking.

How a request travels

Before the first byte of an API response arrives, several things happen, each of which can cost a round trip:

  1. DNS lookup: turn the name (api.example.com) into an IP address, unless it is cached.
  2. TCP handshake: client and server agree to talk, which costs one round trip.
  3. TLS handshake: agree on encryption for HTTPS, which with TLS 1.3 costs another round trip.
  4. HTTP request and response: send the request and wait for the answer.

That is why reusing connections (keep-alive, HTTP/2) and fewer, bigger calls matter. And why a distant server or a mobile network makes every extra round trip hurt.

Designing a good API

  • Use nouns for resources (/orders/17) and let the HTTP method be the verb. Avoid /getOrder.
  • Use the right status codes: 200 success, 201 created, 400 bad request, 401 and 403 for access, 404 not found, 429 too many requests, 500 server error. Do not return 200 with an error inside.
  • Paginate every list, with a limit and a cursor or page, so a response cannot grow without bound.
  • Make retries safe. GET, PUT and DELETE should be idempotent. For POST (create or pay), accept an idempotency key so a retried request does not create two orders.
  • Version your API (/v1/, or a header) and add fields rather than change or remove them.
  • Set timeouts and rate limits, and return clear, consistent errors.

REST vs GraphQL vs gRPC

ConcernRESTGraphQLgRPC
Works directly from a browserYesYesNeeds a proxy (gRPC-Web)
Fits HTTP cachingYes, GETHarderNo
Exact data in one tripNo, unless you add a custom endpointYesYes, by design of the method
Strict typed contractOptional (OpenAPI)Yes (schema)Yes (proto)
Message size and speedLarger (JSON text)MediumSmallest and fastest
StreamingNot nativelySubscriptionsYes
Best forPublic and simple APIsFlexible client screensInternal service calls

Many companies use all three: REST or GraphQL at the edge for apps and partners, and gRPC between internal services.

Avoiding a new single point of failure

The API is the front door, and a few things can make it fragile:

  • A single API server or gateway. Run several behind a load balancer, and keep the gateway itself redundant.
  • One slow dependency. Without timeouts, one slow service makes every caller hang. Set short timeouts and fall back or fail fast.
  • Retries without limits. Unlimited retries from many clients can turn a small failure into an overload (a retry storm). Use backoff, a retry limit and idempotency keys.
  • Breaking changes. A change that breaks old clients is an outage you caused. Version the API and deprecate slowly.

The trade-off: more layers (gateway, versions, limits) in return for stability and protection.

Common mistakes

  • Breaking existing clients. Renaming or removing a field breaks apps you cannot update. Add, do not change, and version when you must.
  • Verbs in URLs and wrong status codes. /getUser and a 200 with an error body confuse clients and caches. Use resources and real status codes.
  • No pagination. One request returns millions of rows and takes the server down. Always page lists.
  • Retrying non-idempotent calls. A retried payment charges twice. Use an idempotency key.
  • A chatty API. One screen needs ten calls, and a slow network makes it crawl. Offer a combined endpoint or a query that returns what the screen needs.
  • No timeouts. One slow service freezes everything that calls it. Set timeouts everywhere.

How to talk about API design in an interview

  • State the clients and what they need, then pick REST, GraphQL or gRPC and say why.
  • List the resources and endpoints, the status codes, pagination, and how you version.
  • Cover safe retries with idempotency keys, and timeouts and rate limits.
  • Say how many round trips a main screen needs and how you keep that low.
  • Name the trade-off: for example, GraphQL's flexibility against caching and server complexity.

Where you meet API design and networking in real systems

Every app talks to a server, and every server talks to other servers. Here are three drawn out, the first with configuration you can run, then more examples.

Example 1: The same profile API in REST, GraphQL and gRPC

A profile screen needs a user, their latest posts and a follower count. Here is how each style describes that contract: an OpenAPI file for REST, a schema for GraphQL, and a .proto file for gRPC. Open the example below to see the picture and the files.

Config: one profile API, three waysSetup 3 short contractsCode no code changes
Clientneeds a profile screenContractOpenAPI, schema or protoServerbuilds the answerResponseJSON or binary
The contract says what can be asked and what comes back. REST usually needs one call per resource, while a GraphQL query or a gRPC method can return the whole screen's data in one trip.
# REST described with OpenAPI 3.0: one URL per resource, standard HTTP methods and status codes.
openapi: 3.0.3
info:
  title: Profiles API
  version: "1.0"
paths:
  /users/{id}:
    get:
      summary: Get one user
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
      responses:
        "200":
          description: The user
          content:
            application/json:
              schema: { $ref: "#/components/schemas/User" }
        "404":
          description: No such user      # a missing resource is a 404, not a 200 with an error body
  /users/{id}/posts:
    get:
      summary: List a user's posts, newest first
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
        - name: limit               # always paginate lists
          in: query
          schema: { type: integer, default: 20, maximum: 100 }
      responses:
        "200":
          description: A page of posts
          content:
            application/json:
              schema:
                type: array
                items: { $ref: "#/components/schemas/Post" }
components:
  schemas:
    User:
      type: object
      required: [id, name]
      properties:
        id: { type: integer }
        name: { type: string }
        photo_url: { type: string, format: uri }
    Post:
      type: object
      required: [id, title]
      properties:
        id: { type: integer }
        title: { type: string }
        body: { type: string }

The OpenAPI file was checked with the openapi-spec-validator library. The GraphQL schema was built with graphql-core, and the example query was validated against it with no errors. The .proto file was compiled with protoc (through grpcio-tools). Names and fields are examples.

Example 2: What happens when you open an API URL

A single request needs a name lookup, a connection, encryption and then the request itself. Reusing a connection skips the middle steps, which is why a second request is faster than the first.

DNS lookupname to addressTCP handshakeone round tripTLS handshakeencryptionHTTP requestthen the response
DNS turns the name into an address, TCP sets up a connection, TLS sets up encryption, and only then is the HTTP request sent. Each step can cost a round trip, which is why connection reuse matters.

Example 3: An API gateway in front of services

Apps usually talk to one public address, an API gateway, rather than to each service. The gateway checks who the caller is, limits how fast they can call, and passes the request to the right service. Behind it, services can talk to each other with gRPC.

MobileWebGatewayUsersPosts
The mobile app and the web app both call the API gateway. The gateway handles authentication and rate limits and forwards requests to the user service and the posts service.

More real-world scenarios

4. Mobile app screens

A mobile screen on a slow network suffers from many round trips. Teams use GraphQL, a combined endpoint, or a backend built for that screen so a view loads with one request.

5. Payments and ordering APIs

When a payment request is retried after a timeout, charging twice would be a disaster. Payment APIs accept an idempotency key with each create request so a repeat returns the first result instead of acting again.

6. Calls between internal services

Inside a company, services call each other thousands of times per second. A typed contract and compact binary messages, as in gRPC, cut size and speed costs and catch mismatches at build time.

7. Live chat and notifications

A chat message should appear as soon as it is sent. WebSockets or server-sent events keep a connection open so the server can push messages, instead of the client asking over and over.

8. Video calls and live streams

A late video frame is useless, so real-time voice and video use UDP-based transports. A lost packet is skipped, not resent, so the call keeps up with real time.

9. Online games

Games send player positions many times a second. UDP lets the newest position arrive quickly, and an old lost update is simply replaced by the next one.

10. DNS and file downloads

A DNS lookup is a tiny question and answer, usually sent over UDP for speed. A file download needs every byte in order, so it uses TCP, which resends anything lost.

Tools and managed services

KindNameNotes
Open sourceOpenAPI and Swagger toolsDescribe and document REST APIs
Open sourceGraphQL, ApolloQuery language and tooling for GraphQL
Open sourcegRPC and Protocol BuffersTyped contracts and binary messages
Open sourceNGINX, Envoy, KongReverse proxies and API gateways
AWSAmazon API GatewayManaged API front door
Google CloudApigee, API GatewayManaged API management
AzureAzure API ManagementManaged API front door

The takeaway

Whenever a design has clients talking to servers or services talking to each other, the first thing you draw is the API contract and the number of round trips, choosing REST, GraphQL or gRPC for the job, and TCP unless a late packet is worthless.

Interview questions

Try answering out loud before you reveal hints. Interviewers care about how you reason, not just the final answer.

  1. 1.

    When would you choose REST, GraphQL or gRPC?

    easy
  2. 2.

    A client times out calling "create payment" and retries. How do you avoid charging twice?

    medium
  3. 3.

    Design pagination for an endpoint that lists a user's posts.

    medium
  4. 4.

    Would you use TCP or UDP for a live video call, a file download and a game, and why?

    easy
  5. 5.

    What happens between typing an API address and the first byte of the response arriving?

    medium

↑ Back to top

On this page