Most people first hear about rate limiting as an anti-abuse tool. Stop scrapers. Block bots. Prevent brute-force logins .Rate Limiting Strategies: Per User Vs Per Token Vs Per Ip With Examples
That’s all true, but it’s not why rate limiting actually matters in production.
In real systems, the first thing that breaks isn’t security. It’s capacity assumptions.
- A single client retrying aggressively can exhaust a downstream service.
- A misconfigured cron job can flatten your database.
- A mobile app update can turn a minor bug into a thundering herd.
Rate limiting exists to put upper bounds on damage. Not just malicious damage accidental, well-intentioned damage too.
If you don’t rate limit, you’re implicitly trusting every client to behave perfectly forever. That never works.
The three strategies and how they really behave
Everyone learns the same three knobs
-
Per-IP
-
Per-token (API key)
-
Per-user
Most explanations stop there. In practice, the interesting part is how they fail.
Per-IP rate limiting: useful, dangerous, unavoidable
Per-IP limiting is the blunt instrument. It’s also the one you end up using whether you like it or not.
Where it works well
Per-IP limits are excellent at catching obvious abuse:
-
Credential stuffing from a single host
-
Scripted scraping with no proxy rotation
-
Accidental infinite loops from one machine
For endpoints like login, password reset, or expensive search queries, per-IP is often the first line of defense because it’s cheap and stateless.
Where it causes real damage
The problem is that IP ≠ user.
I’ve seen per-IP limits:
-
Lock out entire offices behind a corporate NAT
-
Break mobile users on shared carrier IPs
-
Throttle schools, hotels, and coworking spaces into unusability
One time, we limited password reset attempts per IP. A single HR department behind a NAT managed to lock themselves out company-wide. Fun incident review.
Real-world behavior
Per-IP limiting assumes scarcity of IPs. That assumption is wrong in both directions:
-
Attackers rotate IPs cheaply
-
Legitimate users are often forced to share IPs
Per-IP is necessary. It’s just never sufficient.
Per-token / API key limits: isolation and false safety
API keys feel comforting. Each client has an identity. We can rate limit “fairly”.
That’s the theory.
Why API keys are necessary
API keys are essential for:
-
Attribution (who did this?)
-
Revocation (turn one client off)
-
Contract enforcement (plan tiers, quotas)
Without them, everything is guesswork.
Why they’re often misused
The mistake I see constantly: treating API keys as if they represent one workload.
They don’t.
In the real world:
-
One key is used by multiple services
-
Batch jobs and real-time traffic share the same key
-
Retries amplify traffic during partial outages
I’ve seen a single API key generate traffic from 200 pods because someone baked it into a base image.
The limiter did exactly what it was told. The customer still blamed us.
The false sense of safety
Per-key limits give you isolation, not fairness.
They stop one customer from taking down others. They do not guarantee a good experience for that customer.
If you only rate limit per token, you’re outsourcing capacity management to your users whether they know it or not.
Per-user limits: fairness, UX, and expensive mistakes
If you want fairness, you eventually end up at per-user limits.
This is usually the right abstraction. It’s also the hardest to get right.
Why this is usually the right limiter
Users are what you care about:
-
One human spamming refresh shouldn’t hurt others
-
Power users should get more headroom than casual ones
-
Paid tiers should map cleanly to behavior
Per-user limits align with product intent better than IPs or keys.
-
Shared accounts
Teams, dashboards, integrations one “user” can represent many humans or machines.
-
Client behavior you don’t control
Mobile apps retry differently than browsers. Background syncs fire at terrible times. Offline queues flush all at once.
If you don’t design for bursts (we’ll get there), per-user limits feel randomly hostile.
Cost reality
Per-user rate limiting is stateful. It costs memory, coordination, and careful design at scale.
That’s why people avoid it until everything else starts hurting users.
What you should rate limit first
There is no single correct limiter. There is a sensible order.
In systems I trust, the layers look like this:
-
Global safety limit
A hard ceiling protecting the system itself. Rarely hit. Saves you during incidents.
-
Per-IP guardrails
Loose limits. Catch obvious abuse. Assume false positives will happen.
-
Per-token limits
Enforce contracts. Isolate customers. Prevent one key from melting you.
-
Per-user limits
Shape real behavior. Protect UX. Encourage sane client design.
Each layer has a job. None of them are perfect alone.
- If you start with per-user only, you’ll miss abuse.
- If you start with per-IP only, you’ll hurt real users.
- If you stop at API keys, you’ll blame customers for your outages.
NAT and shared IPs: where theory collapses
If you’ve never been burned by NAT, you haven’t operated at scale.
Where this shows up
-
Corporate offices
-
Mobile carriers
-
Universities
-
Hotels and conferences
Thousands of users. One IP. Bursty behavior.
Per-IP rate limiting turns into a denial-of-service for your best users.
What actually works instead
You adapt:
-
Make per-IP limits very forgiving
-
Combine IP with another signal (token, user, session)
-
Detect abuse patterns, not just raw counts
The key mental shift: IP is a hint, not an identity.
Treat it like a weak signal. Never like ground truth.
Burst policies: what people get wrong
“100 requests per minute”.
That breaks normal usage.
Why “no bursts” breaks real clients
Real clients don’t send traffic evenly:
-
Page loads fire multiple requests instantly
-
Mobile apps sync after being offline
-
Background jobs run on the hour
If you don’t allow bursts, users hit limits doing normal things and they can’t fix it.
What a “safe burst” actually means
A burst is permission to exceed the steady rate briefly.
In practice, this means:
-
You care about sustained load, not spikes
-
Short spikes should drain from a bucket, not trip alarms
-
The system must recover quickly
Token bucket vs leaky bucket
Academically, both are well-known.
Operationally:
-
Token buckets are forgiving and user-friendly
-
Leaky buckets feel punitive under retries and jitter
I default to token buckets unless I have a very specific reason not to.
Defaults I actually trust
These are not universal truths. They’re numbers I’ve used without regret.
-
Per-IP
Very high limits. Think “abuse detection”, not fairness.
Example: 1,000 req/min with burst to 2,000. -
Per-user
Lower steady rate, meaningful burst.
Example: 60 req/min with burst to 120. -
Per-token
Based on plan and expected concurrency, not marketing tiers.
Example: 10 req/sec steady, burst to 50.
The important part isn’t the numbers. It’s that bursts exist, and limits reflect how humans and systems actually behave.
Mistakes I’ve actually seen
-
Blocking mobile users because retries counted as abuse
-
Rate limiting login attempts per IP during an outage (locked out everyone)
-
Giving a single API key to a data pipeline and a web app
-
Setting “fair” limits that assumed evenly spaced traffic
-
Treating 429s as “the client’s problem” and ignoring retry storms
Every one of these caused customer pain. None were theoretical.
The mental model that actually works
Stop thinking of rate limiting as a wall.
Think of it as traffic shaping with empathy.
Your goals are:
-
Bound worst-case damage
-
Preserve fairness under load
-
Absorb normal bursts
-
Fail in ways users can recover from
- Every limiter lies a little.
- Every signal is incomplete.
- Every “best practice” has a footnote.
Good rate limiting isn’t about being strict.
It’s about being predictable, forgiving, and hard to abuse at the same time.
You Might Be Interested In
- Top Cybersecurity Certifications Worth Pursuing in 2025
- Why Cybersecurity Is Important?
- Dependency Confusion Prevention: Naming, Registries, And Ci Safeguards
- Why DevOps Improves Software Delivery?
- How Zero Trust Architecture Is Being Adopted by Governments?
Conclusion
Rate limiting only looks simple from a distance. In real systems, it sits at the intersection of unreliable networks, imperfect clients, shared infrastructure, and human behavior. IPs lie, users burst, retries multiply traffic, and “reasonable” limits can turn into outages if they’re designed without empathy for how software actually behaves. The goal isn’t to eliminate abuse completely or enforce perfect fairness it’s to bound damage while letting normal usage flow.
The most reliable systems treat rate limiting as a layered, adaptive control mechanism rather than a single rule. You combine weak signals instead of trusting one, allow short bursts instead of demanding smooth traffic, and accept trade-offs instead of chasing theoretical correctness. When rate limits are predictable, forgiving, and aligned with real usage patterns, they stop being a source of pain and start being one of the quiet systems that keeps everything else standing.
FAQs about Rate Limiting Strategies: Per User Vs Per Token Vs Per Ip With Examples
What is a practical guide to API rate limiting ?
This article is grounded in what actually goes wrong when APIs meet real traffic. It focuses on the failure modes you only see after launch: retries multiplying load, shared IPs triggering false positives, and “reasonable” limits collapsing under bursts. The goal isn’t to present an idealized system, but to explain how rate limiting behaves when users, bugs, and networks don’t cooperate.
Rather than treating rate limiting as a security checkbox, this guide frames it as a reliability tool. It shows how IPs, users, and tokens interact in practice, why layered limits matter, and how small design choices can decide whether your system degrades gracefully or fails loudly.
Learn how rate limiting really works in production?
In production, rate limiting is less about counting requests and more about managing imperfect signals. Per-IP limits are cheap and useful, but they collapse under NAT. Per-user limits feel fair, but they’re harder to scale and easy to misconfigure. This guide explains how these approaches behave under real traffic, not idealized diagrams.
Special attention is given to NAT, mobile networks, and shared environments where “one IP equals one user” simply isn’t true. It also explains why allowing safe bursts is essential for normal usage, and how overly strict limits often punish legitimate users long before they stop abuse.
How doescan engineer’s take on rate limiting beyond theory what to limit first?
Most theoretical explanations assume evenly spaced traffic and well-behaved clients. Real systems never look like that. Traffic comes in spikes, retries amplify load, and background jobs collide in time. This article explains why naïve limits fail under those conditions and how experienced teams prioritize what to protect first.
By focusing on layered defense and realistic burst handling, the article shows how to protect core systems without turning rate limits into random user-facing errors. The emphasis is on sequencing and intent, not rigid rules.
What is Deep, experience-driven insights on API rate limiting, abuse prevention ?
Abuse prevention is only one part of the rate limiting story. Equally important is understanding how legitimate traffic can look abusive during partial outages, client bugs, or network retries. This guide walks through those scenarios and explains why many “best practices” quietly fail in production.
It also explores fairness as a system property, not just a policy choice. Fair limits account for retries, bursts, and shared infrastructure, and they fail in predictable ways. That predictability is what keeps users trusting your platform even when limits are hit.
What is Rate limiting explained by someone who’s fixed outages practical trade-offs?
This perspective comes from fixing systems after they broke, not from designing them in isolation. The defaults and recommendations are shaped by incidents, customer complaints, and postmortems, not just clean architectures. Trade-offs are made explicit, including where accuracy is sacrificed for safety.
The key takeaway is a mental model that treats rate limiting as traffic shaping with empathy. Good limits absorb normal behavior, constrain worst cases, and fail in ways users can recover from. That mindset matters more than any specific algorithm or number.

