Request & Response Design
Required vs optional vs null, response models that are not database rows, over- and under-fetching, batch endpoints, size limits, and file uploads that bypass the API for the bytes.
Every lesson below names the consumers, the design question and the guarantee before recommending anything. Recommendations come with what they cost, when not to use them, and how they evolve.
A request schema is a set of promises about what the server will accept and what each field means. Required vs optional vs nullable, "not sent" vs "sent as null", enums, defaults and the unknown-field policy decide whether the contract can grow — or whether every addition breaks someone.
Serializing the ORM model is the fastest way to ship an endpoint and the most expensive way to own one. A response model is a purpose-built shape — stable ids, explicit types, computed fields, nothing accidental — that lets the table change without the contract noticing.
GET /users/42 returns 80 fields when the screen needs 3; the dashboard makes 8 calls to render once. Both are granularity mismatches between one generic contract and many specific consumers — and the fixes (sparse fieldsets, expansion, GraphQL, a BFF) each move the cost somewhere else.
A client that needs 500 resources can make 500 requests or one. The batch endpoint saves round trips and rate-limit budget — and forces the contract to answer questions a single request never asked: what if item 217 fails, is anything rolled back, and how many requests did that just cost?
Every API has limits on body size, array length, string length, query complexity and file size. The only question is whether the contract states them — with a status code and the number — or whether a load balancer, a JSON parser or the OOM killer states them for you.
The API that handles JSON should not be the pipe for a 3GB video. Create an upload resource, hand the client a signed URL to object storage, confirm completion, then process asynchronously — a four-step contract that keeps the API small, the bytes off your workers, and retries safe.
A consumer who has learned one endpoint should be able to predict every other. Casing, id formats, timestamps, money, envelopes, error shapes and header names are decided once, written in a style guide and enforced by a linter — because consistency is the cheapest documentation an API will ever have.