Platform Account Takeover Card Testing Payment Fraud Pricing Docs Blog
Get a Demo
Blog

Velocity Checks: What They Catch, What They Miss, and How to Set Thresholds

Velocity checks -- measuring how many times a given entity (card, account, IP, device) has transacted in a given time window -- are among the most commonly deployed fraud controls in digital payments. They are also among the most frequently misconfigured. Teams often set thresholds too high to catch fast-moving attacks or too low to avoid blocking legitimate high-frequency users. Getting velocity checks right requires understanding exactly what they are measuring and what they are not.

What velocity checks are actually measuring

A velocity check measures the count of events associated with an entity in a time window. The entity can be a card number, a user account, an IP address, a device fingerprint, an email address, a phone number, or a shipping address. The event is typically a transaction attempt (whether approved or declined), but can also be a login attempt, a payment method add, or any other logged event. The time window is typically between 1 minute and 24 hours, depending on the attack type you are trying to catch.

What velocity checks are not measuring is quality -- they count events without regard to whether those events are suspicious in isolation. A velocity check on card attempts per IP address fires on an IP address that has attempted 10 card payments in 2 minutes regardless of whether those 10 transactions were to legitimate merchants for reasonable amounts or to high-risk recipients for suspicious amounts. The count is the signal; context is absent.

The three most useful velocity dimensions

Card velocity

Card velocity measures how many times a specific card number has been used in a time window. This is the primary signal for card testing -- an attacker running a list of stolen cards through a small-value transaction to validate which cards have available balance will produce elevated velocity on each card in rapid succession. The relevant window for card testing is narrow (1-15 minutes) because automated testing tools process cards quickly.

Card velocity thresholds need to be calibrated by merchant category. A card used 5 times in 10 minutes is suspicious for a single direct merchant but is not suspicious at all on a platform where the card belongs to a shared family account making multiple purchases simultaneously. The threshold that is appropriate for your platform depends on your legitimate use patterns.

Device velocity

Device velocity measures how many distinct transactions a single device fingerprint has initiated in a time window. This is the most useful signal for distributed card testing and for credential stuffing attacks, because automated attacks run from a limited number of devices regardless of how many distinct cards or accounts they access.

Device velocity is more robust to evasion than card or IP velocity because device fingerprints are harder to rotate than IP addresses. An attacker can change IP addresses with a VPN in seconds; generating a convincing new device fingerprint requires more effort. This is why device velocity is a signal worth weighting heavily even when card and IP velocity look normal.

IP velocity

IP velocity is the least reliable of the three for modern fraud patterns. IP addresses are trivially rotatable through proxy networks and VPN services. An attacker who is targeting a platform with IP-level velocity controls will rotate IPs aggressively; the velocity check will show each IP at 1-2 transactions and never trigger. IP velocity still catches the least sophisticated attacks -- automated scripts running from a single server IP -- but serious card testing operations have moved past it.

IP velocity is most useful when combined with another signal: an IP that has been seen in a prior fraud incident AND has 3+ transactions in an hour is a meaningful combined signal even if neither condition alone would be actionable.

Common threshold mistakes and how to avoid them

Setting thresholds based on intuition, not data

The most common velocity check misconfiguration we see is thresholds set at round numbers (10 per hour, 5 per day) with no empirical basis. These numbers are often either too permissive (a card testing bot that processes 8 cards per hour evades the 10/hour rule) or too restrictive (a family account that has 6 legitimate transactions in a day gets blocked by a 5/day rule).

Threshold calibration should start from your transaction data. Pull a 90-day sample of legitimate transactions and compute the distribution of per-entity velocity -- how many transactions did typical cards, devices, and IPs produce in hourly and daily windows? Set your threshold at the 99th percentile of legitimate traffic to minimize false positives while still catching velocity well above normal levels.

Using a single threshold across all time windows

Card testing attacks happen at different speeds. Automated attacks run at maximum speed (potentially hundreds of cards per minute from a single device); semi-automated attacks run more slowly to avoid rate limits (a few cards per hour); manual attacks may be spread over days. A single hourly velocity threshold catches the fast automated attacks but misses the slow deliberate ones.

Effective velocity monitoring uses multiple windows: 5-minute, 1-hour, 24-hour. The 5-minute window catches automated attacks. The 1-hour window catches semi-automated attacks. The 24-hour window catches distributed attacks spread to evade short-window checks. Each window has its own threshold calibrated to the distribution of legitimate traffic in that window.

Measuring only successful transactions

Velocity checks that count only approved transactions miss the most informative signal for card testing: the decline rate. A card testing operation generates many declines -- the whole point is to identify which cards work by testing them until one is approved. A velocity check on total attempts (approved + declined) is much more sensitive to card testing than one that only counts approvals.

More specifically: the ratio of declines to total attempts in a velocity window is often a better signal than raw count alone. An IP with 5 total attempts in an hour and 0 declines is probably a legitimate user. An IP with 5 total attempts in an hour and 4 declines is testing cards. The same raw count, very different risk profile.

What velocity checks miss entirely

Even well-configured velocity checks have fundamental blind spots. They measure frequency within a single entity's history, not patterns across entities. A card testing operation that uses each stolen card exactly once avoids all per-card velocity checks. An account takeover campaign that compromises and fraudulently uses one account per day avoids all per-account velocity checks.

These are the distributed patterns that require graph-level analysis: the same device fingerprint appearing on multiple distinct accounts, the same IP range appearing across multiple users, cards from the same BIN sequence being used at the same platform within hours of each other. Velocity checks on individual entities cannot see these cross-entity patterns; they require a scoring layer with graph features.

This is why we describe velocity checks as one component in a layered fraud stack rather than a standalone control. They are effective at catching concentrated attacks on a single entity and provide a strong signal-to-noise ratio for those patterns. For distributed attacks that stay below per-entity thresholds by design, they need to be complemented by behavioral and graph-level scoring that can see the cross-entity pattern.

Implementing velocity checks with Riskgrove

When you pass device_id, user_id, ip_address, and session_id fields to the Riskgrove scoring API, our feature pipeline computes velocity signals across all four dimensions on every scoring request. The multi-window velocity features (5-minute, 1-hour, 24-hour) are pre-computed features in the gradient-boosting model, weighted according to their historical predictiveness for your transaction type.

The risk_score incorporates these velocity signals alongside the broader signal set, which means elevated velocity on a single dimension contributes proportionally to the score without requiring you to write separate velocity rules. For platforms that do maintain their own rules alongside Riskgrove, avoid double-counting: if you are already using Riskgrove velocity signals via the score, adding duplicate velocity rules in your own rules engine will generate redundant declines that increase false positives without adding fraud coverage.