Back to System Design Index

Free Course15 lessonsLive diagramsMukul

API Design in Production: 15 Lessons From the Gateway

Nine years of Golang on AWS taught me one discipline: name the promise, price the boundary, and retire versions before they retire you. Each lesson starts from a real production failure, states its assumptions up front, and ends in math you can re-run. The bill hides in the boundary.

TL;DR: Fifteen forensic API lessons with live diagrams, from contracts to idempotency and rate limits and deprecation math. Built from production postmortems with calculators for the math.

By Mukul Kumar Mishra · Backend and SRE course · Updated October 23, 2026

What you will be able to do

How interviews test this course: clarify scope first, estimate out loud second, break your own design third. Lesson 14 rehearses the bench.

Lesson 01 · Foundations · The contract ships first

The Contract Is the Product

Clients outlive every implementation behind them. Stripe reported $1.4 trillion in 2024 total payment volume; that dollar-volume figure is not a transaction count or proof that every payment succeeded exactly once. Its API documentation describes idempotency keys for safely retrying eligible requests. Design the promise before the handler.

clients contract handlers promise kept
  • Name resources as nouns and actions as verbs. Verbs in URLs age into lies the moment a second client arrives.
  • One contract, many handlers. Keep the client-visible promise stable while implementation details change.
  • Deep dive: Stripe's $1.4T 2024 Volume: Idempotency and a Modeled Scale Teardown, with documented API behavior and explicitly modeled rates.
Interview room

Q1. Design checkout for a store doing 40,000 RPS. What is your first endpoint?

Q2. A partner stored your v1 response shape in their warehouse. How do you ship v2?

Promise named. Now keep it across versions. Lesson 02: Versioning →

Lesson 02 · Evolution · Change without casualties

Version Without Breakage

Every breaking change is a migration you force on strangers. Salesforce once queued logins behind one shared path on conference day two, which is what a forced migration feels like at scale. Ship v2 beside v1. Measure adoption. Sunset with dates and headers, never with surprises.

v1 live v2 beside adopt up sunset dated
  • Prefer URL versions for public APIs and header versions for partners who negotiate. Either works when the sunset date is contractual.
  • Emit Sunset and Deprecation headers on every old response. Clients that can see the deadline meet the deadline.
  • Deep dive: Salesforce Dreamforce Login Stall, with a reported service symptom and an explicitly modeled queue explanation.
Interview room

Q1. Your mobile app has a 6-week review lag. How do you version?

Q2. When is header versioning better than URL versioning?

Versions live side by side. Now make retries safe. Lesson 03: Idempotency →

Lesson 03 · Safety · Retries that cannot double charge

Idempotency Keys End Double Charges

Networks retry. The API contract must distinguish a retry of one intent from a new operation. Stripe's documentation says an eligible request with the same idempotency key can reuse its saved result instead of repeating the operation. This is an API behavior, not a claim of global exactly-once processing across every downstream system.

intent keyed request ledger check one charge
Interview room

Q1. Design fund transfer with at-least-once delivery. Where does the key live?

Q2. A client reuses one key for two different payments. What breaks?

Retries made safe. Now cap the flood. Lesson 04: Limits →

Lesson 04 · Capacity · Admission is a budget

Rate Limits Are Capacity

Azure West US taught the industry that retries multiply a 75 percent capacity loss into a 6 times overload at the surviving edge. Limits at the gateway turn that flood into a queue with fast errors instead of slow timeouts. Scale without limits replays the incident faster. Limits without scale prolongs the pain. Together they converge.

flood in token bucket queue waits edge holds
  • Gate per key and per route and per region. One bucket per dimension, each with its own refill math.
  • Return 429 with Retry-After and a limit-policy header. Clients that can compute backoff will back off.
  • Deep dive: Azure West US Route Withdrawal, admission math at 1.4M offered RPS.
Interview room

Q1. Size a token bucket for 90k burst RPS against 12k steady. Show the refill.

Q2. When do you shed with 429 versus queue with 202?

Flood gated. Now write the contract down. Lesson 05: OpenAPI →

Lesson 05 · Contracts · Specs that generate trust

OpenAPI Turns Promises Into Artifacts

Thirteen thousand postings in ninety days ask for REST API skill, and five thousand ask for OpenAPI by name. The spec is the contract clients code against, mocks run from, and gateways enforce. A spec reviewed like code prevents the drift that becomes the midnight page.

spec review codegen out mocks run gateway enforces
  • Lint specs in CI: no verb URLs, no unpaged lists, no undocumented errors. Red spec blocks the merge.
  • Generate server stubs and client SDKs and mocks from one source. Three artifacts, zero drift.
  • Deep dive: Razorpay Kafka, what happens when client contracts meet partition limits.
Interview room

Q1. Your spec has 200 endpoints. How do you review it without drowning?

Q2. Codegen versus hand-written SDKs. When does each win?

Contract written. Now place the enforcement. Lesson 06: Topology →

Lesson 06 · Topology · Where the policy lives

Gateway Versus Mesh

A gateway enforces at the border. A mesh enforces between every pair of services. Use the gateway for client-facing policy such as auth and limits and versioning. Use the mesh for service-to-service policy such as mTLS and per-route budgets. One border, many interiors. Confusing the two buys two bills and one gap.

edge in gateway mesh inside policy both held
  • Terminate TLS and validate auth and apply limits at the gateway. Fail fast before interior spend.
  • Run mTLS and retries and timeouts in the mesh. Interior policy travels with the call, not the docs.
  • Deep dive: Cell-Based Control Planes, bulkheads that hold when maps fail.
Interview room

Q1. Draw a request path for a checkout call through a gateway and mesh. Label every policy point.

Q2. When does a mesh add more risk than it removes?

Policy placed. Now prove identity. Lesson 07: Auth →

Lesson 07 · Identity · Every call proves itself

Auth at the Edge

None of your handlers should parse credentials. The edge validates tokens, checks scopes, and forwards identity downstream as headers services can trust. OAuth scopes carry permission. mTLS carries workload identity. IAM carries cloud permission. Mix them deliberately or attackers will mix them for you.

call arrives token checked scope mapped identity set
  • Validate and cache JWKS with short TTLs. Google's us-west1 report lists IAM among services affected by regional network degradation; it does not identify token validation as the cause.
  • Scope per action, not per service. Broad scopes turn one leaked token into a skeleton key.
  • Deep dive: GCP us-west1, where a fiber-maintenance capacity loss reached IAM and other dependent products.
Interview room

Q1. Design a scope model for a marketplace with buyers, sellers and admins.

Q2. Your JWKS endpoint slows to 4 seconds. What breaks first?

Identity settled. Now survive the callback. Lesson 08: Webhooks →

Lesson 08 · Async · Callbacks that survive the night

Webhooks at Scale

Webhook endpoints receive asynchronous events and can fail independently of the original request. Stripe's documentation says live-mode delivery can retry for up to three days and does not guarantee event order. Sign each payload, deduplicate processed event IDs, and isolate slow destinations in your own design.

event fires per-dest queue signed retry acked done held
  • HMAC-sign payloads with rotating secrets and versioned signatures. Unsigned callbacks are rumors.
  • Set a retry policy that fits your service. Stripe documents retries for up to three days in live mode; its public docs do not specify an eight-attempt schedule.
  • Deep dive: Stripe's $1.4T 2024 Volume: Idempotency and a Modeled Scale Teardown, including webhook delivery limits and modeled load.
Interview room

Q1. Design webhook delivery for 1M events with 5 percent failing endpoints.

Q2. How do you rotate signing secrets without dropping trust?

Callbacks tamed. Now page through millions. Lesson 09: Paging →

Lesson 09 · Scale · Lists that do not fall over

Pagination Discipline

Offset pagination scans deeper with every page, which means page 10,000 costs a full table walk. Cursor pagination walks an index forward at constant cost. At Discord trillions-of-messages scale the difference is the cluster. Default to cursors. Reserve offsets for admin UIs with small result sets.

list asked cursor set index walk page flat
  • Encode cursor as opaque token with sort key and tiebreaker. Clients iterate, never compute.
  • Cap page size and enforce max window. A client asking for a million rows is asking for your outage.
  • Deep dive: Discord message storage, hot partitions and quorum fan-in.
Interview room

Q1. Price offset page 50,000 against cursor page 50,000 at 1M rows. Show the gap.

Q2. When is offset pagination still the right call?

Lists flattened. Now fail usefully. Lesson 10: Errors →

Lesson 10 · Clients · Failures they can act on

Errors Clients Can Handle

Every error must answer three questions: what happened, whether retry helps, and what to do next. Machine-readable codes, retryable flags, and request IDs make failures easier to diagnose. Salesforce Trust reported that some customers could not create support cases during its September 16 disruption while public status updates continued; its record does not say all support channels were unavailable.

fail fast code set retry flagged traced id
  • Mark every error retryable or terminal. Ambiguous errors breed the retry storms of Lesson 04.
  • Echo a request ID in every response and every log line. Correlation without IDs is archaeology.
  • Deep dive: Salesforce Dreamforce Login Stall: 16 Instance IDs, 7h36m, with the status record separated from the queue model.
Interview room

Q1. Design an error catalog for payments with 12 failure modes.

Q2. Your 500s spike. How does a client tell retryable from fatal?

Failures legible. Now retire the old. Lesson 11: Sunsets →

Lesson 11 · Economics · Retiring versions for profit

Deprecation Economics

Every live version bills forever: test matrices and docs and support and incident surface. Deprecation converts that annuity into a project with a date. Announce early, header every response, offer a migration sandbox, then delete. Versions are inventory. Inventory rots.

announce date headers warn sandbox helps delete ships
  • Price each live version per quarter: CI minutes and support tickets and incident share. Publish the number internally.
  • Give migration sandboxes with diff tooling. The version that is easy to leave is the version clients actually leave.
  • Deep dive: Figma Multiplayer, per-document isolation as versioning discipline.
Interview room

Q1. Two versions cost how much per quarter? Model it for your fleet.

Q2. A top customer refuses migration. What is your playbook?

Old retired. Now price the whole gateway. Lesson 12: Billing →

Lesson 12 · Money · The gateway invoice

The Gateway Bill

Assume 1M RPS through gateway and auth and limits at a modeled $0.0000012 per origin request. That is about $1.20 per second, or about $103,700 per day, before data and support (1M x 86,400 x $0.0000012; illustrative scenario, not a measured invoice). Shedding 65 percent of a modeled ~5M RPS storm for five hours saves about $70,000 in origin compute at the same unit rate (0.65 x 5M x 18,000s x $0.0000012). Run the RPS Envelope calculator with your own numbers. The bill hides in the boundary. Here the boundary has a rate limit.

steady 12k burst 148k gated 35k modeled bars, not invoices
  • Model per-request cost as gateway and auth and origin. Three lines, no mysteries.
  • Hold headroom as insurance with a published price. Unpriced headroom gets cut the quarter before the storm.
  • Deep dive: Azure West US, the full invoice model.
Interview room

Q1. Price your gateway at current RPS with modeled unit cost. What dominates?

Q2. A storm triples offered load. What does the gated invoice read?

Invoice priced. Now rehearse breakage. Lesson 13: Contracts →

Lesson 13 · Practice · Prove compatibility continuously

Breaking-Change Drills

Consumer-driven contracts flip testing: consumers publish what they need, providers verify every build against those pacts. A pact suite that runs per commit catches the renamed field before it ships. Pact tests are cheaper than apologies by roughly three orders of magnitude. Run them like billing depends on it.

pacts published build verifies break caught ship safe
  • Collect pacts from top consumers first. Ten pacts catch more breakage than ten thousand unit tests of shape.
  • Verify pacts in CI and canary. A pact that only runs nightly is a history book.
  • Deep dive: Kafka Rebalance Explained, contract discipline under protocol change.
Interview room

Q1. Design a pact suite for 3 consumers sharing one checkout API.

Q2. A pact breaks at 2 AM. Roll forward or roll back?

Breakage rehearsed. Now face the panel. Lesson 14: Interviews →

Lesson 14 · Careers · The API interview bench

The Interview Bench

API interviews test three moves: clarify scope first, estimate out loud second, break your own design third. Rate-limiting questions want bucket math. Webhook questions want retry horizons. Versioning questions want sunset plans. Answer with numbers and tradeoffs and one story from these lessons. Panels hire engineers who price their own designs.

clarify scope estimate aloud break it price it
  • Open with throughput and latency and consistency asks. Five minutes of questions saves forty of redesign.
  • Close every answer with failure modes and cost. Designs without prices are sketches.
  • Deep dive: System Design Course, Lesson 01 starts from outages.
Interview room

Q1. Design rate limiting for 100M users in 45 minutes. Talk while you draw.

Q2. Tell me about an API breakage you caused and fixed.

Bench warmed. Now ship for real. Lesson 15: Capstone →

Lesson 15 · Capstone · One contract, three clients

Ship One API

Start small on purpose. One resource, three clients, one gateway. Write the OpenAPI spec, generate mocks, gate with buckets, sign webhooks, publish pacts, run a breaking-change drill, price the month. An API you have broken on purpose is the only kind you understand.

spec written drills passed month priced modeled bars, not invoices
  • Run the fourteen drills from lessons 1 through 13 against one real contract. Gaps show at a glance.
  • Kill a version mid-week and measure migration. Untested sunsets are rumors with headers.
  • Close with the invoice. Requests per month times modeled unit price, labeled as estimates.
Interview room

Q1. Ship the spec and gateway config to one reviewer. What do they flag?

Q2. Your webhook endpoint goes dark Friday night. Walk the runbook.

Course complete. Interview the whole system next: System Design: 15 Lessons From Real Outages

Sources and method

This course teaches from published Buildopsy postmortems linked under each lesson: Stripe idempotency, Razorpay client contracts, Salesforce queues, Azure admission math, Discord pagination, Figma isolation, Kafka protocol discipline, and the gateway invoice model. Incident details follow those accounts. Cost framing is modeled from public list prices.