Rate limiting caps how many requests a client may make in a period of time. The server tracks usage per client key, accepts requests inside the budget, and answers the rest with 429 Too Many Requests and a Retry-After header.
An API without a rate limit is only as available as its most aggressive caller. A buggy retry loop, a scraper, or a credential stuffing attack can consume all of the database connections and CPU that every other client depends on. Rate limiting gives each client a budget and enforces it before the request reaches expensive code.
Every limiter answers the same question, has this key made too many requests recently, but they differ in what they store. A fixed window keeps one counter per clock-aligned window. A token bucket keeps a fractional token count and a timestamp, refilling continuously and allowing bursts up to the capacity. A sliding window log keeps the timestamp of each accepted request and counts the ones inside the last N seconds, which is exact but costs one entry per request.
The key decides what is being protected. Limiting by IP address is the default at the edge and stops anonymous floods, but shared NATs and mobile carriers put thousands of users behind one address. Limiting by API key or user id after authentication is fairer and lets you sell tiers. Many systems apply both, a loose IP limit at the load balancer and a per-account limit in the application.
The state has to be shared. A Map inside one Node process only limits that process, so three instances behind a load balancer silently triple the budget. Production limiters keep counters in Redis and run the check and the update as one atomic operation, either INCR with EXPIRE or a short Lua script, so two instances cannot both read 2 and both accept when the limit is 3.
Interview framing: define Rate Limiting in one sentence, then explain one concrete runtime behavior and one common pitfall with a short code example.