Share this letter & I’ll send you some rewards for the referrals.
Some of these API design concepts are foundational, and some are advanced. ALL of them are super useful to software engineers building scalable APIs.
Curious to know how many were new to you:
REST,
GraphQL,
Authentication,
Authorization,
Rate Limiting,
Caching,
Pagination,
Status Codes,
Webhooks,
Idempotency,
API Gateway,
API Versioning,
JSON,
OAuth 2.0,
HTTP Methods,
gRPC,
API Keys.
(…and much more in Part 2!)
For each, I’ll share:
What it is & how it works (in plain English),
A real-world analogy (if I found one),
Tradeoffs,
Why it matters.
Let’s go!
§
Beyond the Coding Agent: Building at Enterprise Scale (Partner)
Coding agents made individual tasks faster. They didn’t remove the coordination, validation, and handoffs that actually determine how fast enterprise software ships.
Join Sid, CTO and Co-founder of Blitzy, for a live session on what changes when a system can hold context across an entire codebase, not just a single file or function. Sid will walk through a real project in Blitzy, covering everything from reverse engineering and tech spec generation to the Agent Action Plan, code generation, and PR Review. You’ll see what happens at each stage and where human review gates the process.
What you’ll see:
Reverse engineering and tech spec generation on a real codebase
Where human review sits in an autonomous build: sign-off at the plan stage, approval at the merge stage
Enterprise modernization results
We’ll close with an open Q&A, so bring your questions on agent orchestration and governance at scale.
(Thanks to Blitzy for partnering on this newsletter.)
§
1. REST
Representational State Transfer (REST) is a way to build APIs that organizes data as resources and uses standard HTTP methods to work with them.
Every resource gets its own address.
Each resource has its own URL. For example, a user is at /users/42 and an order is at /orders/17.
Use:
GETto read it,POSTto create it,PUTto replace it,DELETEto remove it.
The HTTP method defines the action, and the URL identifies the resource. Both the client and server follow the same contract.
REST also stays stateless, so any server can answer any request.
Analogy
A library with a fixed shelf number for every book:
You hand the librarian a shelf number and say borrow, return, or replace. They never ask what you meant.
The number identifies the book; the verb identifies the action; they leave no room for guessing.
Tradeoff
REST wastes requests & bandwidth.
One screen may need a user, their orders, and their payment method, which costs three round trips. Ask for a user, and the server sends every field, including the twenty you ignore. Add a field for one client, and you risk breaking another.
So keep your resources small and reach for GraphQL when clients need to shape their own responses.
Why it matters
Public APIs, mobile and web clients, anything cached at the edge, and any service where a new developer should guess the right endpoint on the first try.
Spring, Express, Django REST Framework, and FastAPI all lean on it. Pair it with OpenAPI so the contract stays readable, and with API Versioning so today’s shape survives tomorrow’s change.
2. GraphQL
GraphQL is a query language for APIs that lets clients request exactly the data they need in a single response.
There is one endpoint instead of dozens.
Client sends a query that names the fields it needs. The server walks the query, fetches each field, and returns a response shaped like the request. Queries read data, mutations change it, and subscriptions stream updates as they happen. Ask for three things at once, and you get one round trip.
The client decides the shape, so the server stops guessing.
Analogy
A sandwich counter where you name every ingredient:
A fixed combo hands you the pickles you scrape off and skips the extra cheese you wanted. Naming each ingredient gets you the sandwich you meant to order, in one pass down the counter.
Tradeoff
GraphQL costs you more.
Caching gets harder because every query is a POST to the same URL. Plus one careless nested query could walk your database for a minute. You carry a schema, a resolver for every field, and a plan for the N+1 problem.
So set a depth limit and a query cost budget on day one.
Why it matters
Mobile clients on slow networks, screens that stitch together several resources, and front ends that change faster than the backend.
Apollo, Relay, Hasura, and graphql-js are common choices. Pair it with Rate Limiting, because a single expensive query can cost more than a thousand REST calls.
3. Authentication
Authentication proves “who” is calling your API.
The caller presents a credential & server checks it.
That credential could be a password, an API key, or a signed token. The server verifies it against something it trusts, then attaches an identity to the request. Everything downstream reads that identity.
A caller who fails the check gets a 401 and never reaches the business logic.
Analogy
Showing your passport at the border desk.
The officer compares the photo to your face & the name to a list. They are not deciding where you may travel inside the country. They only confirm you are the person on the document.
Tradeoff
Each check costs a lookup/signature verification.
Secrets leak through logs, screenshots, and public repositories. Sessions expire at the worst moment for the user.
So rotate credentials on a schedule & keep them out of your URLs.
Why it matters
Every API that touches private data, money, or a user account.
Auth0, Okta, Keycloak, and Firebase Auth handle the hard parts. Pair it with Authorization, because proving who you are says nothing about what you may do.
4. Authorization
Authorization decides what a proven caller is allowed to do.
Authentication runs first, then authorization runs.
The server knows the identity & now checks the rules:
Does this user own this order?
Does this token carry the write scope?
Does this role permit a delete?
A caller who fails the check gets a 403 i.e., the server knows exactly who you are and still says no.
Authorization answers a second question: what may you touch?
Analogy
A hotel keycard.
The card proves nothing about your name. It opens your room and the gym on the third floor. It stays dead against the manager’s office and the room next door, no matter how many times you tap it.
Tradeoff
Rules sprawl across the codebase, and one missing check becomes a breach.
Test the negative cases, because a passing test that proves a user can read their own order says nothing about whether they can read somebody else’s.
So check ownership at the data layer & at the route.
Why it matters
Multi-tenant systems, admin panels, and any endpoint where one user’s record sits next to another’s.
Role-based access control and attribute-based access control are the two common models. Pair it with OAuth 2.0, whose scopes carry authorization decisions across service boundaries.
5. Rate Limiting
Rate limiting caps how many requests one caller can send in a time window.
The server counts & past the cap, refuses them.
A common limit is a hundred requests per minute per API key. Cross it, and the server returns 429 Too Many Requests along with a Retry-After header. Response headers usually report the ceiling and how much of it you have left, so a well-behaved client slows itself down before it gets refused.
One noisy caller stops starving everyone else.
Analogy
A nightclub with a counter at the door.
The room holds four hundred people. The doorman counts everyone in & everyone out. When the room is full, the next person waits outside, and the people already dancing keep enjoying the music.
Tradeoff
Limits frustrate honest heavy users, and a limit that seems generous in testing looks tight during a launch.
Counting across many servers means shared state, which is one more thing that can go down. Token bucket handles bursts better than a fixed window.
Why it matters
Public APIs, free tiers, login endpoints, and any expensive operations like search or export.
Redis backs most implementations, and NGINX, Envoy, and Kong ship it built in. Pair it with throttling, which slows a caller instead of turning them away.
6. Caching
Caching stores a copy of the response so next identical request skips extra work.
The fastest request is the one your server never handles.
A cache sits between the client and the origin and holds recent responses. When a matching request arrives, the cache answers from memory in a millisecond. Cache-Control headers say how long a copy stays fresh. An ETag lets the client ask whether its copy is still good, and the server answers 304 Not Modified without sending the body again.
Read-heavy APIs live/die on this.
Analogy
A barista who writes your usual on a card.
You walk in; they glance at the card, and the drink is ready before you finish greeting them. They only ask again when you tell them your order has changed.
Tradeoff
Cached data goes stale, and a user who updates their profile & still sees the old name loses trust immediately. Knowing when to throw a copy away is one of the hard problems in computing.
So cache aggressively on data that rarely changes. Plus, never cache a private response in a shared layer.
Why it matters
Product catalogs, public profiles, search results, and anything a thousand people read for every one person who writes.
Redis, Memcached, Varnish, and any content delivery network do this well. Pair it with Headers, which carry every instruction a cache obeys.
7. Pagination
Pagination returns large datasets in smaller pages instead of sending ALL results in one response.
The client asks for a slice and gets a pointer to the next one.
Offset pagination takes a page number & size, then skips ahead.
Cursor pagination hands back an opaque marker that says where you stopped, and you pass it back to continue.
Both return the rows plus enough information to fetch the following page…Your database, your network, and the client’s memory will thank you.
Analogy
A book with a bookmark.
Nobody reads a thousand pages in one sitting. You read twenty, slide the ribbon in, and close the cover. Tomorrow you open straight to the ribbon rather than counting pages from the front.
Tradeoff
Offset pagination drifts…Insert a row while somebody reads page two, and they see a duplicate on page three.
Cursor pagination gives up the ability to jump anywhere except forward & back.
So use cursors for feeds & offsets for admin tables.
Why it matters
Every list endpoint, every feed, and every export.
Stripe, GitHub, and Slack all publish cursor-based APIs. Pair it with Filtering and Sorting, which decide what lands on the page before you slice it.
§
Reminder: this is a teaser of the subscriber-only newsletter, exclusive to my golden members.
When you upgrade, you’ll get:
High-level architecture of real-world systems.
Deep dive into how popular real-world systems work.
How real-world systems handle scale, reliability & performance.
(If this newsletter has helped you become a better software engineer, consider subscribing to support my work.)










