Skip to main content

API Design and Rate Limiting

REST API basics​

Model resources with nouns and use HTTP methods for actions.

OperationRequestSuccess
ListGET /users200
ReadGET /users/42200
CreatePOST /users201 + Location
ReplacePUT /users/42200 / 204
UpdatePATCH /users/42200
DeleteDELETE /users/42204

Good practices​

  • Version the API (/v1/...) and keep changes backwards compatible.
  • Return consistent error bodies and correct status codes.
  • Use idempotency keys for non-idempotent operations such as payments.
  • Authenticate with tokens (OAuth 2, JWT) and always use HTTPS.

Pagination​

StyleProsCons
Offset / limitSimple, jump to a pageSlow on large offsets, unstable when data changes
Cursor (keyset)Fast, stableCannot jump to arbitrary pages
GET /posts?limit=20&cursor=eyJpZCI6MTIzfQ

Rate limiting​

Protects services from abuse and overload. Respond with 429 Too Many Requests and a Retry-After header.

AlgorithmIdeaNotes
Fixed windowCount per time windowBurst at window edges
Sliding windowSmooth count over a moving windowMore accurate, more memory
Token bucketTokens refill at a rate; each request takes oneAllows bursts, widely used
Leaky bucketRequests drain at a constant rateSmooths traffic
token_bucket.py
import time

class TokenBucket:
def __init__(self, rate, capacity):
self.rate, self.capacity = rate, capacity
self.tokens, self.last = capacity, time.monotonic()

def allow(self):
now = time.monotonic()
self.tokens = min(self.capacity,
self.tokens + (now - self.last) * self.rate)
self.last = now
if self.tokens >= 1:
self.tokens -= 1
return True
return False

In a distributed setup keep counters in a shared store (for example Redis with atomic operations), keyed by user, API key or IP.