Rate Limiting & Abuse Economics · Chapter 4 of 5
What an attack costs both sides
Model attacker spend against attacker return, and defender cost against defender loss — with every number labelled as illustrative.
Security controls rarely make an attack impossible. They make it expensive. If an attack costs more than it returns, rational attackers go elsewhere. That framing — abuse economics — is the most useful lens for setting rate limits, because it turns arbitrary thresholds into answers to a question: at what point does this attack stop paying? This chapter builds simple cost models for both sides. Every figure in this chapter is an illustrative example, chosen to show the method, not to describe any real market.
The attacker’s ledger
An attacker’s cost per attempt combines infrastructure (proxies, compute), friction solving (challenges, proof-of-work), and inputs (stolen credentials, phone numbers). Their return per success depends on what the account yields: resale value, funds that can be moved, or — for pumping — revenue share per message. Expected profit per attempt is success probability times return, minus cost. When that is negative, the attack stops being worth running at scale.
// Illustrative example — not real market prices
attacker = {
proxyCostPerRequest: 0.0004, // USD
challengeSolveCost: 0.002, // per solved challenge
credentialCost: 0.01, // per leaked credential pair
returnPerTakeover: 40, // resale value of a funded account
}
pSuccessPerAttempt = (1 - accountsWithStrongMFA) * passwordReuseRate * otpBypassRate
expectedProfit = pSuccessPerAttempt * returnPerTakeover - costPerAttemptEach control moves one term. Per-challenge budgets and cooldowns lower otpBypassRate. Proof-of-work and challenges raise costPerAttempt. Passkey adoption lowers the share of accounts that can be taken over at all. Notifications and holds lower returnPerTakeover, because a takeover reversed within the hour yields nothing. You do not need accurate numbers to use the model; you need to know which term each proposal changes and roughly by how much.
Attacker view
My break-even
- I stop when profit per attempt is negative across my best targets.
- I shift to whichever endpoint has the weakest friction.
- Cheap challenges barely register; reversed takeovers hurt.
- I go after the long tail of accounts without strong factors.
Defender view
Moving the break-even
- Raise cost on the cheapest entry point first.
- Reduce return with fast notification and reversible holds.
- Shrink the pool of OTP-only accounts with passkey adoption.
- Measure attacker behaviour after each change; they adapt.
A worked pumping model
Pumping has the cleanest economics because both sides pay per message. Suppose, as an illustrative example, that each pumped message costs the defender 0.06 USD and returns 0.02 USD to the attacker after intermediaries take their share. The attacker’s costs are per request: proxy and challenge solving. If Quillon adds a proof-of-work step that costs the attacker 0.025 USD of compute per request, each attempt now loses money even if the message is sent. Add a per-prefix breaker that stops sends after a few hundred unverified messages, and the attacker’s maximum gain per prefix is capped regardless of cost.
The defender side of the same model: before controls, a pumping night like the one in series 3 might cost several thousand USD. A proof-of-work step costs engineering time and adds roughly a second of latency for new clients. The breaker costs some legitimate sends during incidents. If the expected monthly loss avoided exceeds the friction and build cost, the control pays for itself. Write those estimates next to the control in the threat register, labelled as estimates.
Credential stuffing against OTP accounts
For takeovers, the model shows why per-challenge budgets matter more than per-IP limits. With five attempts per code, a blind attacker’s chance against one code is five in a million per challenge, or fifteen in a million with a ±1 TOTP window. Even at a return of 40 USD per takeover, the expected value of a challenge is a fraction of a cent, less than the cost of the proxy request and credential that produced it. The attack only becomes profitable when the attacker bypasses the code entirely — through relay, SIM swap or recovery flows — which is why series 2 and 3 matter more than any threshold.
- Guessing is unprofitable once per-challenge budgets exist; stop tuning it.
- Bypass routes (relay, SIM swap, recovery) dominate attacker returns.
- Pumping is profitable until per-message cost or per-prefix caps flip the sign.
- Support-desk social engineering is cheap for attackers; price it in.
The defender’s hidden costs
Defender cost is not only engineering time. Friction loses honest users: each extra second or challenge at signup reduces completion. Support costs rise when legitimate users are locked out. Brand damage follows publicised incidents. An honest model includes these, because a control that stops an attack but costs more in abandoned signups than the attack would have cost is a bad trade. Chapter 5 is about measuring and minimising exactly that cost.
Ravi Castellanos, Quillon’s product lead, insisted on one rule after the first modelling session: every abuse control ships with a friction metric next to its effectiveness metric. Signup completion rate, verify success rate and support contact rate are tracked per control, so the team can see when a defence starts hurting more than it helps.
To use the model in a planning meeting, list each proposed control, name the single term it moves, and estimate the direction and rough size of the change. Controls that move no term, or only move it slightly, are easy to drop. Controls that flip the sign of attacker profit on your cheapest entry point go to the top of the list.
// bench check
0/3 correct · 0 answered
1. Which term does a fast notification-and-hold control mainly move?
2. Why does tuning OTP guessing limits further rarely pay off?
3. What must every figure in an abuse cost model carry until measured?