6 min read
Web Backend Fundamentals Index
Tier 1 -- Core Web & API Basics
Authentication & Authorization
Tier 2 -- Communication Models
Tier 3 -- Production & API Hardening
Web Backend Fundamentals Index
Tier 1 -- Core Web & API Basics
Authentication & Authorization
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.
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?
2. How It Works in Practice
Core Constraints
- Client-Server: UI and data storage are separated. The frontend and backend evolve independently.
- Stateless: Every request contains all the information the server needs. No state on the server between requests. This is what makes horizontal scaling easy.
- Cacheable: Responses should declare whether they can be cached, enabling proxies and browsers to reduce load.
- Uniform Interface: Resources are identified by URLs, manipulated via representations (JSON/XML), and accessed through standard verbs.
- Layered System: Clients don't need to know if they're talking to the actual server or a load balancer/cache/proxy.
- 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:
| Verb | Meaning | Idempotent? | Safe? |
|---|---|---|---|
| GET | Read | Yes | Yes |
| HEAD | Like GET but no body | Yes | Yes |
| POST | Create or trigger | No | No |
| PUT | Replace (full update) | Yes | No |
| PATCH | Partial update | No* | No |
| DELETE | Delete | Yes | No |
*PATCH can be made by design but is not required to be.
Status code conventions for :
| Scenario | Status |
|---|---|
| Resource created | 201 Created + Location header |
| Successful read | 200 OK |
| Empty collection | 200 OK with [], not 404 |
| No content to return | 204 No Content |
| Validation error | 422 Unprocessable Entity |
| Auth required | 401 Unauthorized |
| Forbidden | 403 Forbidden |
| Not found | 404 Not Found |
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?
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:
ModelViewSetauto-generates all REST endpoints - Rails:
resources :ordersgenerates 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.
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?
4. Trade-offs and Common Mistakes
REST vs. alternatives
| REST | GraphQL | gRPC | |
|---|---|---|---|
| Best for | Public APIs, CRUD | Flexible client queries | Internal microservices |
| Flexibility | Medium | High (client selects fields) | Low (strict schema) |
| Over/under-fetching | Common problem | Solved by design | Solved by design |
| Browser support | Native | HTTP only | Needs proxy for browsers |
| Learning curve | Low | Medium | High |
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.
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?
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.
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?
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)
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?
Glossary History
Click dotted jargon to save explanations here.
Glossary History
Click dotted jargon to save explanations here.