The Physics of APIs: Idempotency, Rate Limits & State Machines
REST is not just CRUD. The physics of Idempotency (f(x) = f(f(x))), Leaky Bucket Rate Limiting, and why HATEOAS is a State Machine.
🎯 What You'll Learn
- Prove Idempotency mathematically ($f(x) = f(f(x))$)
- Implement Token Bucket Rate Limiting (Redis Lua Script)
- Design APIs as Finite State Machines (HATEOAS)
- Master Versioning Physics (Header-based vs URL-based)
- Differentiate 429 vs 503 (Backpressure Physics)
📚 Prerequisites
Before this lesson, you should understand:
Introduction
Most developers treat APIs as “JSON over HTTP”. This is wrong. An API is a Remote Procedure Call with Failure Semantics. When you send a request over a network, three outcomes are possible:
- Success.
- Failure.
- Unknown (The request was sent, but the connection dropped before response).
This “Unknown” state creates the need for Idempotency.
The Physics: Idempotency
Definition: An operation is idempotent if applying it multiple times has the same effect as applying it once.
- GET: Idempotent (Read-only).
- PUT: Idempotent (Replace state). . If I say twice, is still .
- POST: Not Idempotent (Create). If I say “Pay 20.
The Solution: Idempotency Keys.
The client generates a UUID (v4) and sends it in the header: Idempotency-Key: <uuid>.
The server stores the Key + Response in Redis.
If the client retries, the server returns the stored response execution.
Rate Limiting: The Token Bucket
If an API accepts infinite requests, it will crash. We need Backpressure.
Token Bucket Algorithm:
- Capacity (): Maximum burst size.
- Refill Rate (): Tokens added per second.
Physics Metaphor: A bucket leaks water at a constant rate. You can dump a bucket of water in (Burst), but if you pour faster than the leak, it overflows (429 Too Many Requests).
Redis Lua Implementation: To avoid race conditions (Get-then-Set), we use Lua to make the check atomic.
-- Redis Lua Script for Token Bucket
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then
return 0 -- Rejected
else
redis.call("INCR", key)
redis.call("EXPIRE", key, 1) -- 1 Second Window
return 1 -- Accepted
end
HATEOAS: The API as a State Machine
REST stands for “Representational State Transfer”. Most APIs are just “RPC over JSON”. True REST uses HATEOAS (Hypermedia As The Engine of Application State).
Physics: The Server dictates the State Machine. The Client just follows transitions.
Response Example:
{
"order_id": 123,
"status": "pending_payment",
"links": [
{ "rel": "pay", "method": "POST", "href": "/orders/123/pay" },
{ "rel": "cancel", "method": "DELETE", "href": "/orders/123" }
]
}
If the status changes to paid, the pay link disappears.
The Client never needs to know the logic “If pending, show pay button”. It just renders the links.
Practice Exercises
Exercise 1: Idempotency Fail (Beginner)
Task: Write a Python script that POST /charge twice without an Idempotency Key.
Observation: You effectively double-charge the user.
Fix: Add a UUID header and handle it on the server.
Exercise 2: The 429 Governor (Intermediate)
Task: Use ab (Apache Bench) to hammer your API.
Action: Implement the Lua Token Bucket.
Result: See requests succeed up to Limit, then fail with 429 immediately.
Exercise 3: State Machine Logic (Advanced)
Task: Design a “Traffic Light” API.
Action: Return links for next_state.
Rules: Red -> Green (links: next). Green -> Yellow (links: next). Yellow -> Red.
Check: Ensure you cannot go from Red to Yellow.
Knowledge Check
- Which HTTP method is NOT idempotent?
- What is the formula for Idempotency?
- Why use Lua for Rate Limiting in Redis?
- What does HATEOAS stand for?
- Difference between 429 and 503?
Answers
- POST. (And PATCH, usually).
- f(x) = f(f(x)).
- Atomicity. Prevents race conditions between reading usage and incrementing it.
- Hypermedia As The Engine of Application State.
- 429: Client sending too fast. 503: Server is overloaded/down.
Summary
- Idempotency: The safety net for network uncertainty.
- Rate Limiting: Protecting the server from physics (infinite load).
- HATEOAS: The API tells the Client what is possible.
Questions about this lesson? Working on related infrastructure?
Let's discuss