Skip to main content
SMS pumping (also called artificially inflated traffic, or AIT) is a fraud pattern where attackers trigger OTP messages to phone numbers they control (often premium-rate or VOIP numbers) and collect the revenue your SMS provider pays out. You pay per message; they profit per delivery. A single unprotected OTP endpoint can generate thousands of dollars in SMS charges overnight. The attack is simple to script and hard to notice until your SMS bill arrives. The fix is catching it before the message is sent: evaluate the phone number and the sending velocity against your otp policy, and only fire the SMS if tracenow clears it.

Which event this protects

SMS pumping maps to the otp event. The Cloudflare Worker fires it on every POST to your OTP-send route, before your app calls your SMS provider. If the verdict is deny, the message is never sent and you pay nothing.

How it works

When a request hits your OTP endpoint, the Worker:
  1. Reads the phone number from the request body and the IP from the request.
  2. Attaches the device fingerprint token.
  3. Calls /trace with event: otp; phone enrichment and velocity checks run in parallel.
  4. Evaluates your SMS pumping policy.
  5. deny → the Worker returns a block response; your SMS provider is never called. allow/challenge → forwarded to your app.

Signals used

See Signals for the full field reference.
Fully covered at the edge. SMS-pumping signals (phone quality, IP, velocity, device) are all available before sign-in, so the Cloudflare Worker covers this use case with no backend code. Add the optional server-side call only if you want per-user OTP-failure velocity tied to a real account.

Set it up

Fastest setup: enable the pre-built SMS pumping policy templates in Monitor mode instead of building these rules by hand. The steps below show what each template contains, so you can tune them afterward.
1

Connect Cloudflare (if you haven't already)

In the dashboard under Integration, paste a Cloudflare API token with Workers Scripts: Edit and Zone → DNS: Read scopes. tracenow validates the token and lists your zones.
2

Add a route rule for your OTP endpoint

Under Integration → Routes, add a rule:
  • Route pattern: e.g. yourdomain.com/api/auth/otp or yourdomain.com/send-otp
  • Method: POST
  • Event: otp
  • Mode: start with Monitor to observe real traffic before blocking
3

Enable the SMS pumping policies

Under Guard, enable the pre-built SMS pumping policy templates for the otp event in Monitor mode. To customize or add your own rules, see Rules.
4

Switch to Enforce mode

After reviewing Monitor traces and confirming the rules catch the right traffic, edit the OTP route and change Mode to Enforce. Click Deploy.In Enforce mode, deny verdicts stop the request at the edge, so your SMS provider never receives the call. This is the critical step: the protection only prevents charges when Enforce mode is active.
Start with Monitor mode for at least 24–48 hours before switching to Enforce. An overly aggressive velocity rule could deny OTPs for legitimate users (e.g., users on shared corporate IPs). Review the trace feed first.

Rules

You don’t build these by hand. The pre-built SMS pumping policy templates cover these patterns and enable in one click. See Rules to customize them or add your own.

What a caught attempt looks like

A pumping run produces many traces like this in the event feed:
The duration_ms on OTP traces is typically low. Phone enrichment is fast, so by the time you’d call your SMS provider, the verdict is already back.

Going further

The Cloudflare layer is the right tool for SMS pumping. OTP requests are pre-authentication, so there’s no user ID to attach, and the edge evaluation is sufficient. If your app verifies an OTP code (not just sends it), you can send a follow-up /trace call with status: succeeded or status: failed after the user enters the code. This seeds OTP failure velocity, which lets you catch accounts that request many codes but never enter a valid one: a signal of probing or credential enumeration.
The velocity.user.failed_count_1h signal on the otp event then catches accounts burning through OTP codes, a pattern distinct from the sending-side abuse the Cloudflare layer catches. See server-side integration for the full request and response reference.