REST Architecture

6 min read

Reading Progress0%
Web Backend Fundamentals Index
Tier 1 -- Core Web & API Basics
Tier 2 -- Communication Models
Tier 3 -- Production & API Hardening
Web Backend Fundamentals Index
Tier 1 -- Core Web & API Basics
Tier 2 -- Communication Models
Tier 3 -- Production & API Hardening

REST Architecture

1. What It Is

(Representational State Transfer) is an architectural style — a set of constraints — for designing networked APIs. It was defined by Roy Fielding in his 2000 doctoral dissertation, but what matters for engineers is the practical result: APIs are the dominant style for -based web services.

REST does not prescribe a format or protocol. In practice, "REST API" almost always means: verbs + JSON + resource-based URLs.

Why it matters: virtually every backend engineer will design, build, or consume REST APIs. Interviewers expect fluency in REST conventions and the ability to explain trade-offs.


QUICK CHECK

A backend engineer is describing their team's public API to a new hire: 'We use resource-based URLs, standard HTTP verbs like GET, POST, and PUT, and return JSON responses.' Which architectural style does this API follow?

Choose one answer

2. How It Works in Practice

Core Constraints

  1. Client-Server: UI and data storage are separated. The frontend and backend evolve independently.
  2. Stateless: Every request contains all the information the server needs. No state on the server between requests. This is what makes horizontal scaling easy.
  3. Cacheable: Responses should declare whether they can be cached, enabling proxies and browsers to reduce load.
  4. Uniform Interface: Resources are identified by URLs, manipulated via representations (JSON/XML), and accessed through standard verbs.
  5. Layered System: Clients don't need to know if they're talking to the actual server or a load balancer/cache/proxy.
  6. Code on Demand (optional): Servers can send executable code (e.g., JavaScript). Rarely used.

The Uniform Interface in Practice

Resources, not actions. models everything as a noun (resource), not a verb (action).

Good REST:
  POST /orders          → create an order
  GET  /orders/42       → fetch order 42
  PUT  /orders/42       → replace order 42
  PATCH /orders/42      → partial update order 42
  DELETE /orders/42     → cancel order 42

Not REST (RPC-style):
  POST /createOrder
  POST /getOrder?id=42
  POST /cancelOrder

verb semantics:

VerbMeaningIdempotent?Safe?
GETReadYesYes
HEADLike GET but no bodyYesYes
POSTCreate or triggerNoNo
PUTReplace (full update)YesNo
PATCHPartial updateNo*No
DELETEDeleteYesNo

*PATCH can be made by design but is not required to be.

Status code conventions for :

ScenarioStatus
Resource created201 Created + Location header
Successful read200 OK
Empty collection200 OK with [], not 404
No content to return204 No Content
Validation error422 Unprocessable Entity
Auth required401 Unauthorized
Forbidden403 Forbidden
Not found404 Not Found

QUICK CHECK

A developer is building a REST API for an e-commerce platform. For the endpoint that cancels an order, they need to choose the right HTTP verb. A client accidentally sends the same cancel request twice due to a network retry. Which verb should be used, and why?

Choose one answer

3. Common Real-World Usage

CRUD APIs: most APIs map directly to database tables — create, read, update, delete. Every web framework has routing built in.

  • Express.js: router.get('/users/:id', handler)
  • Django REST Framework: ModelViewSet auto-generates all REST endpoints
  • Rails: resources :orders generates the full set of routes
  • FastAPI: @app.get("/items/{item_id}")

Pagination: REST doesn't standardize pagination. Common patterns:

  • Offset-based: GET /posts?page=2&per_page=20
  • Cursor-based: GET /posts?cursor=abc123&limit=20 (better for real-time data)

Filtering and sorting: GET /orders?status=pending&sort=created_at:desc

Versioning: GET /v1/users or Accept: application/vnd.api.v2+json. URL versioning is more common.

Nested resources: GET /users/42/orders — reasonable for tight ownership. Avoid deep nesting (/a/b/c/d/e); flatten when relationships are loose.


QUICK CHECK

A social media app displays a live feed of posts that updates frequently. Engineers need to implement pagination for the /posts endpoint. Which pagination strategy is the better fit, and why?

Choose one answer

4. Trade-offs and Common Mistakes

REST vs. alternatives

RESTGraphQLgRPC
Best forPublic APIs, CRUDFlexible client queriesInternal microservices
FlexibilityMediumHigh (client selects fields)Low (strict schema)
Over/under-fetchingCommon problemSolved by designSolved by design
Browser supportNativeHTTP onlyNeeds proxy for browsers
Learning curveLowMediumHigh

Common Mistakes

Verbs in URLs: POST /createUser breaks the uniform interface. Use POST /users.

Using GET for mutations: GET /users/42/delete bypasses semantics — browsers/caches can call it accidentally.

Overusing POST: not every non-CRUD operation needs to be POST /doSomething. Model side effects as resource state changes. E.g., publishing an article: PUT /articles/42/status with body {"status": "published"}.

Inconsistent naming: mixing /userAccounts, /user_profiles, /Users in the same API. Pick a convention (plural nouns, kebab-case or snake_case) and stick to it.

Ignoring status codes: returning 200 OK with {"error": "not found"} in the body. Clients must parse every body to detect errors; status codes exist precisely so they don't have to.

Not versioning early: adding breaking changes without a version strategy forces all clients to update simultaneously.

Stateful server design called "": if your server stores state (and the client doesn't send everything it needs per request), it is not stateless — it's just HTTP.


QUICK CHECK

An API currently handles article publishing via POST /publishArticle with a body containing the article ID. A developer wants to refactor this to follow REST conventions more closely. Which endpoint design best models this operation as a resource state change?

Choose one answer

5. Interview Angle

How to explain it

" is an architectural style built on top of . The key ideas are: model your API around resources (nouns in URLs), use verbs for actions, keep the server stateless so every request is self-contained, and use standard status codes to communicate outcomes."

Common interview questions

Q: What makes an API RESTful? A: It follows constraints — primarily stateless, resource-based URLs, standard HTTP verbs and status codes, and a uniform interface.

Q: What is idempotency and why does it matter? A: An operation is if running it multiple times produces the same result as running it once. GET, PUT, DELETE are ; POST is not. Idempotency matters for safe retries — a network failure on a PUT can be retried without side effects.

Q: How would you handle a non-CRUD operation in REST? A: Model it as a state transition on a resource. E.g., sending an email can be POST /emails (create and send). Approving a loan can be PATCH /loans/42 { "status": "approved" }.

Q: REST vs. — when would you choose each? A: REST for public APIs, simple CRUD, or when HTTP caching matters. when clients have complex, varying data needs (e.g., a mobile app that fetches 30 different shapes of data). GraphQL reduces over/under-fetching at the cost of caching complexity.


QUICK CHECK

Your mobile app needs to approve a loan. The operation doesn't map cleanly to creating or deleting a resource — it's a state change. Which REST-style endpoint design best handles this?

Choose one answer

6. Practical Examples

User resource API

POST   /users                 → create user         → 201 + Location: /users/99
GET    /users/99              → get user            → 200
PATCH  /users/99              → update email        → 200
DELETE /users/99              → delete user         → 204

GET    /users?role=admin&page=1&per_page=20  → list users → 200

Response envelope (practical convention)

// GET /users/99
{
  "id": 99,
  "email": "alice@example.com",
  "created_at": "2024-01-15T10:30:00Z"
}

// GET /users?page=1
{
  "data": [...],
  "pagination": {
    "total": 240,
    "page": 1,
    "per_page": 20,
    "next_cursor": "eyJpZCI6MjB9"
  }
}

// 422 response
{
  "error": "validation_failed",
  "details": [
    { "field": "email", "message": "must be a valid email address" }
  ]
}

FastAPI route example

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
    email: str
    name: str

@app.post("/users", status_code=201)
async def create_user(payload: UserCreate):
    user = await db.create_user(payload.email, payload.name)
    return user  # FastAPI serializes to JSON

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    user = await db.find_user(user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

@app.patch("/users/{user_id}")
async def update_user(user_id: int, payload: dict):
    user = await db.update_user(user_id, payload)
    return user

@app.delete("/users/{user_id}", status_code=204)
async def delete_user(user_id: int):
    await db.delete_user(user_id)
QUICK CHECK

A client sends a POST request to /users to create a new account. The server successfully creates the user with ID 99. Which HTTP status code and response header combination correctly follows REST conventions for this operation?

Choose one answer