Skip to content

Adaptive Rate Limiting & Velocity-Based Threat Detection

Mindful Auth implements adaptive rate limiting to detect and prevent distributed attacks, credential stuffing, and account takeovers. Unlike fixed rate limiting (which only tracks attempts per email), adaptive rate limiting analyzes attack patterns across multiple dimensions.

Plan Availability: Core security features work on all plan tiers (Free, Pro, Business). Audit log visibility of these events requires Business plan. Free and Pro plans get the security enforcement without the audit trail.


Layer 1: Velocity-Based Rate Limiting (Distributed Attack Detection)

Section titled “Layer 1: Velocity-Based Rate Limiting (Distributed Attack Detection)”

Purpose: Detect when the same email is targeted from multiple IPs in a short time window.

Use Case: Prevents distributed credential stuffing attacks where attackers use botnets or proxy networks to bypass single-IP rate limits.

Applies to: Login attempts

How it works:

  • Tracks unique IPs attempting login for the same email within a 15-minute sliding window
  • Calculates risk level based on unique IP count:
    • Low risk (1-2 IPs): Normal behavior
    • Medium risk (3-4 IPs): Unusual pattern, logged but allowed
    • Critical risk (5+ IPs): Distributed attack detected, account locked for 30 minutes

Cloudflare KV Key: login_velocity:{emailHash} (global, no tenant prefix)

  • Generated via loginVelocityKey(env, email) helper
  • Uses centralized HMAC-SHA256 hashing for PII protection

Implementation:

worker/src/utils/auth/velocityTracking.js
const velocityCheck = await trackLoginVelocity(env, request, email);
if (!velocityCheck.allowed) {
return jsonResponse({
authorized: false,
message: 'Too many login attempts from different locations.'
}, 429, env);
}

Audit Events:

  • login_velocity_violation (riskLevel: critical) - Account locked due to velocity threshold
  • login_velocity_suspicious (riskLevel: high/medium) - Suspicious pattern detected but allowed

Layer 2: Progressive Lockout (Repeat Offender Penalties)

Section titled “Layer 2: Progressive Lockout (Repeat Offender Penalties)”

Purpose: Increase lockout duration exponentially for accounts repeatedly locked due to failed login attempts.

Use Case: Deters persistent attackers by making each subsequent attack attempt more costly (longer lockout).

How it works:

  • Tracks lockout count per email over 30-day retention period
  • Escalates lockout duration with each violation:
    • 1st lockout: 1 hour
    • 2nd lockout: 4 hours
    • 3rd lockout: 24 hours
    • 4th+ lockout: 7 days

Cloudflare KV Key: lockout_history:{emailHash} (30-day TTL)

  • Generated via lockoutHistoryKey(env, email) helper
  • Uses centralized HMAC-SHA256 hashing for PII protection

Implementation:

const progressive = await trackProgressiveLockout(env, userEmail, recordId);
newAttempts.lockedUntil = new Date(Date.now() + progressive.lockoutDurationMs).toISOString();

User-Facing Impact:

  • First-time mistake: Short 1-hour lockout (reasonable for legitimate users)
  • Persistent attacks: Escalating penalties make brute-force attacks impractical

Layer 3: Geo-Anomaly Detection (Impossible Travel Detection)

Section titled “Layer 3: Geo-Anomaly Detection (Impossible Travel Detection)”

Purpose: Flag suspicious login attempts from geographically distant locations in a short time window.

Use Case: Detect account takeover attempts where attacker logs in from a different country than the legitimate user.

How it works:

  • Stores last 5 successful login locations (country + city) per email
  • On each login attempt, compares current location to recent history
  • Flags as anomaly if:
    • Medium risk: Login from new country (but more than 6 hours since last login)
    • High risk: Login from new country within 6 hours of last login (impossible travel)

Cloudflare KV Key: geo_history:{emailHash} (90-day retention)

  • Generated via geoHistoryKey(env, email) helper
  • Uses centralized HMAC-SHA256 hashing for PII protection

Requirements:

  • Uses ipgeolocation.io API for IP → location lookups
  • Falls back gracefully if API key missing (geo-anomaly detection disabled, no impact on login)
  • Results cached in Cloudflare KV for 90 days to minimize API calls

Implementation:

const ip = request.headers.get('CF-Connecting-IP');
const geoData = await getGeoForIp(env, ip);
const geoAnomaly = await detectGeoAnomaly(env, email, recordId, geoData?.location?.country, geoData?.location?.city);
if (geoAnomaly.anomaly) {
// Log to audit but allow login (non-blocking detection)
await logAuditEvent(env, request, {
eventType: 'login_geo_anomaly',
riskLevel: geoAnomaly.riskLevel,
message: `Login from ${geoAnomaly.currentCountry} (previous: ${geoAnomaly.previousCountry})`
});
}

Update History After Successful Login:

await updateGeoHistory(env, email, geoData?.location?.country, geoData?.location?.city);

Audit Events:

  • login_geo_anomaly (riskLevel: high/medium) - Non-blocking detection for tenant review

Important: Geo-anomaly detection is non-blocking by design. It logs the anomaly to audit logs but does not prevent login. This is intentional because:

  • Users may legitimately travel or use VPNs
  • GeoIP data is not 100% accurate
  • Tenants can review audit logs and manually lock accounts if needed (Business plan only)

Layer 4: Registration Velocity Tracking (Spam & Harassment Prevention)

Section titled “Layer 4: Registration Velocity Tracking (Spam & Harassment Prevention)”

Purpose: Prevent spam account creation and email harassment via registration flows.

Use Case: Stops attackers from creating mass accounts or repeatedly trying to register someone else’s email to spam them with verification emails.

Applies to: Password registration (/auth/register-password) and Magic Link registration (/auth/register-magic-link)

How it works:

  • IP-based limit: Max 5 registrations per IP per hour (prevents single-source spam)
  • Email-based limit: Max 3 registration attempts per email per hour (prevents harassment)
  • Distributed attack detection: Flags 3+ different IPs trying to register same email as suspicious, blocks at 5+ IPs

Cloudflare KV Keys:

  • registration_ip:{ipHash} (1-hour TTL) - Generated via registrationIPKey(env, ip) helper
  • registration_velocity:{emailHash} (1-hour TTL) - Generated via registrationVelocityKey(env, email) helper
  • Both use centralized HMAC-SHA256 hashing from worker/src/utils/kv/kvKeys.js

Implementation:

const ipCheck = await trackRegistrationByIP(env, request);
if (!ipCheck.allowed) {
return jsonResponse({ success: false, message: ipCheck.message }, 429, env);
}
const velocityCheck = await trackRegistrationVelocity(env, request, email);
if (!velocityCheck.allowed) {
return jsonResponse({ success: false, message: velocityCheck.message }, 429, env);
}

Audit Events:

  • registration_ip_banned (riskLevel: high) - IP exceeded registration limit
  • registration_velocity_violation (riskLevel: critical/high) - Email registration velocity exceeded
  • registration_velocity_suspicious (riskLevel: high/medium) - Multiple IPs registering same email

Thresholds:

  • IP limit: 5 registrations per hour → 1-hour ban
  • Email harassment: 3 registration attempts per hour → 1-hour block
  • Distributed attack: 5+ different IPs → 1-hour block

Magic Link Specific Behavior:

  • Registration velocity applies at registration time (when account is created)
  • Existing magic link login rate limiting (requestMagicLink.js) remains separate (3-minute cooldown per email)
  • This prevents both spam account creation AND harassment via verification emails

Layer 5: Verification Resend Velocity Tracking (Email Harassment Prevention)

Section titled “Layer 5: Verification Resend Velocity Tracking (Email Harassment Prevention)”

Purpose: Prevent attackers from spamming verification emails to victim’s inbox via resend verification endpoint.

Use Case: Stops email harassment attacks where an attacker repeatedly requests verification emails for someone else’s account.

Applies to: Email verification resend (/auth/resend-verification)

How it works:

  • IP-based limit: Max 10 verification resend requests per IP per hour (prevents single-source spam)
  • Email-based velocity: Tracks unique IPs requesting verification for same email, detects distributed harassment
  • Calculates risk level:
    • Low risk (1-2 IPs): Normal behavior
    • High risk (3-4 IPs): Suspicious pattern, logged but allowed
    • Critical risk (5+ IPs): Harassment attack detected, blocked for 1 hour

KV Keys:

  • resend_verification_ip:{ipHash} (1-hour TTL) - Generated via resendVerificationIPKey(env, ip) helper
  • resend_verification_velocity:{emailHash} (1-hour TTL) - Generated via resendVerificationVelocityKey(env, email) helper
  • Both use centralized HMAC-SHA256 hashing from worker/src/utils/kv/kvKeys.js

Implementation:

const ipCheck = await trackResendVerificationByIP(env, request);
if (!ipCheck.allowed) {
return jsonResponse({ success: false, message: ipCheck.message }, 429, env);
}
const velocityCheck = await trackResendVerificationVelocity(env, request, email);
if (!velocityCheck.allowed) {
return jsonResponse({ success: false, message: velocityCheck.message }, 429, env);
}

Audit Events:

  • verification_resend_ip_banned (riskLevel: high) - IP exceeded verification request limit
  • verification_resend_velocity_violation (riskLevel: critical) - Email harassment attack detected
  • verification_resend_velocity_suspicious (riskLevel: high) - Multiple IPs requesting verification

Thresholds:

  • IP limit: 10 verification requests per hour → 1-hour ban
  • Email harassment: 5+ different IPs → 1-hour block
  • Suspicious threshold: 3+ different IPs → logged but allowed

Section titled “Layer 6: Magic Link Request Velocity Tracking (Email Harassment Prevention)”

Purpose: Prevent attackers from spamming magic link emails to victim’s inbox via magic link login endpoint.

Use Case: Stops email harassment attacks where an attacker repeatedly requests magic links for someone else’s email.

Applies to: Magic link login request (/auth/request-magic-link)

How it works:

  • IP-based limit: Max 10 magic link requests per IP per hour (prevents single-source spam)
  • Email-based velocity: Tracks unique IPs requesting magic links for same email, detects distributed harassment
  • Calculates risk level:
    • Low risk (1-2 IPs): Normal behavior
    • High risk (3-4 IPs): Suspicious pattern, logged but allowed
    • Critical risk (5+ IPs): Harassment attack detected, blocked for 1 hour

KV Keys:

  • magic_link_request_ip:{ipHash} (1-hour TTL) - Generated via magicLinkRequestIPKey(env, ip) helper
  • magic_link_request_velocity:{emailHash} (1-hour TTL) - Generated via magicLinkRequestVelocityKey(env, email) helper
  • Both use centralized HMAC-SHA256 hashing from worker/src/utils/kv/kvKeys.js

Implementation:

const ipCheck = await trackMagicLinkRequestByIP(env, request);
if (!ipCheck.allowed) {
return jsonResponse({ success: false, message: ipCheck.message }, 429, env);
}
const velocityCheck = await trackMagicLinkRequestVelocity(env, request, email);
if (!velocityCheck.allowed) {
return jsonResponse({ success: false, message: velocityCheck.message }, 429, env);
}

Audit Events:

  • magic_link_request_ip_banned (riskLevel: high) - IP exceeded magic link request limit
  • magic_link_request_velocity_violation (riskLevel: critical) - Email harassment attack detected
  • magic_link_request_velocity_suspicious (riskLevel: high) - Multiple IPs requesting magic links

Thresholds:

  • IP limit: 10 magic link requests per hour → 1-hour ban
  • Email harassment: 5+ different IPs → 1-hour block
  • Suspicious threshold: 3+ different IPs → logged but allowed

Core Security Enforcement:

  • ✅ Velocity-based rate limiting (blocks distributed attacks)
  • ✅ Progressive lockout penalties (exponential backoff)
  • ✅ Geo-anomaly detection (location tracking)
  • ✅ Registration velocity tracking (spam & harassment prevention)
  • ✅ Account locking in backend (authentication_status = "Locked")
  • ✅ Cloudflare KV-based tracking (login_velocity, lockout_history, geo_history, registration limits)
  • ✅ 429/403 error responses to attackers

What you get: Full protection against distributed attacks, credential stuffing, and account takeovers. Your users are secure regardless of plan tier.

Audit Log Visibility:

  • 📊 login_velocity_violation events logged
  • 📊 login_velocity_suspicious events logged
  • 📊 login_geo_anomaly events logged
  • 📊 login_locked events with lockoutCount metadata
  • 📊 registration_velocity_violation events logged
  • 📊 registration_ip_banned events logged
  • 📊 Full Cloudflare context (IP, ASN, geo, User-Agent)
  • 📊 Audit log dashboard and analytics

What you get: Everything from Free/Pro PLUS detailed audit trail for monitoring, alerting, and compliance reporting.

When auditLogsStatus = 'Disabled' (Free/Pro plans):

if (tenantCfg.auditLogsStatus !== 'Active') {
// Silently skip audit logging for non-premium tenants
return;
}

All logAuditEvent() calls return early without writing. The security enforcement happens before audit logging, so Cloudflare KV updates and account locks proceed normally. Free/Pro tenants get protected but don’t see the audit trail.

All plan tiers can implement custom account locking:

  • Create backend automation (Tape, Make.com, Zapier, n8n, etc.)
  • Define custom conditions (business rules, field changes, manual admin actions)
  • Update authentication_status = "Locked" in backend
  • Call /auth/lock-account endpoint to invalidate sessions (requires internal API key)

Business plan advantage:

  • Can create automations that REACT to Mindful Auth’s audit log events
  • Example: Auto-lock account when login_geo_anomaly detected
  • Example: Flag account for review after multiple login_velocity_suspicious events
  • Example: Permanent ban after 5+ login_locked events in 30 days

Free/Pro plan approach:

  • Implement custom locking based on backend fields and business logic
  • Manual admin review and locking when suspicious activity suspected
  • Cannot automate based on Mindful Auth’s security events (no audit log access)

Both approaches use the same /auth/lock-account endpoint - audit logs are for monitoring, not for the locking mechanism itself.


Attack: Attacker tries 100 passwords from one IP address.

System Response:

  1. First 3 failed attempts: Normal handling, incrementing counter
  2. 4th failed attempt triggers standard rate limiting
  3. Account locked for 1 hour (1st lockout)
  4. Audit event: login_locked (riskLevel: high)

Velocity tracking: Not triggered (only 1 IP)


Scenario 2: Distributed Credential Stuffing

Section titled “Scenario 2: Distributed Credential Stuffing”

Attack: Attacker uses 15 different IPs to try leaked passwords (1 attempt per IP).

System Response:

  1. First 2 IPs: Normal attempts (low risk)
  2. IPs 3-4: Medium risk, logged to audit
  3. 5th IP triggers velocity lockout
  4. Account locked for 30 minutes
  5. Audit event: login_velocity_violation (riskLevel: critical)

Result: Attack stopped after just 5 distributed attempts, preventing credential stuffing.


Scenario 3: Persistent Attacker (Repeat Offender)

Section titled “Scenario 3: Persistent Attacker (Repeat Offender)”

Attack: Attacker repeatedly attempts to brute-force account over multiple days.

System Response:

  1. Day 1: Account locked for 1 hour (1st lockout)
  2. Day 2: Account locked for 4 hours (2nd lockout)
  3. Day 3: Account locked for 24 hours (3rd lockout)
  4. Day 4+: Account locked for 7 days (4th+ lockout)

Result: Attack becomes economically unfeasible due to exponential time penalties.


Scenario 4: Account Takeover via Stolen Credentials

Section titled “Scenario 4: Account Takeover via Stolen Credentials”

Attack: Attacker logs in from Russia with correct password (user is in USA).

System Response:

  1. Password validates successfully
  2. Geo-anomaly detected: Login from Russia (previous: USA, last login 2 hours ago)
  3. Audit event: login_geo_anomaly (riskLevel: high) - Business plan only
  4. Login succeeds (non-blocking)
  5. Business plan: Tenant automation reacts to audit log, auto-locks account
  6. Free/Pro plans: Tenant uses custom backend logic/manual review to detect and lock

Result: Attack succeeds initially but can be detected and stopped:

  • Business plan: Automated response via audit log triggers
  • Free/Pro plans: Manual review or custom backend automation

Attack: Attacker creates 10 accounts from one IP within 30 minutes.

System Response:

  1. First 5 registrations: Allowed (below IP threshold)
  2. 6th registration attempt triggers IP ban
  3. IP blocked for 1 hour
  4. Audit event: registration_ip_banned (riskLevel: high)

Result: Attack stopped at 5 accounts, preventing further spam.


Scenario 6: Email Harassment via Registration

Section titled “Scenario 6: Email Harassment via Registration”

Attack: Attacker repeatedly tries to register victim@example.com from different IPs to spam them with verification emails.

System Response:

  1. First 2 registration attempts: Allowed
  2. 3rd registration attempt triggers email velocity limit
  3. Email blocked for 1 hour (all IPs)
  4. Audit event: registration_velocity_violation (riskLevel: high, reason: email_harassment)

Result: Victim receives max 2 verification emails, protected from harassment.


Scenario 7: Distributed Registration Attack (Botnet)

Section titled “Scenario 7: Distributed Registration Attack (Botnet)”

Attack: Botnet uses 10 different IPs to register victim@example.com.

System Response:

  1. First 2 IPs: Normal registration attempts
  2. IPs 3-4: Medium risk, logged as suspicious
  3. 5th IP triggers distributed attack detection
  4. Email blocked for 1 hour (all IPs)
  5. Audit event: registration_velocity_violation (riskLevel: critical, reason: distributed_registration_attack)

Result: Attack stopped before overwhelming victim with verification emails.


Scenario 8: Email Harassment via Verification Resend

Section titled “Scenario 8: Email Harassment via Verification Resend”

Attack: Attacker repeatedly requests verification emails for victim@example.com (who already has an unverified account) using different IPs to spam their inbox.

System Response:

  1. First 2 IPs: Verification emails sent (low risk)
  2. IPs 3-4: High risk, logged as suspicious
  3. 5th IP triggers harassment detection
  4. Email blocked for 1 hour (all IPs)
  5. Audit event: verification_resend_velocity_violation (riskLevel: critical, reason: verification_harassment_attack)

Result: Victim receives max 4 verification emails, protected from inbox spam.


Section titled “Scenario 9: Email Harassment via Magic Link Requests”

Attack: Attacker repeatedly requests magic links for victim@example.com (who has an active account) using different IPs to spam their inbox.

System Response:

  1. First 2 IPs: Magic links sent (low risk)
  2. IPs 3-4: High risk, logged as suspicious
  3. 5th IP triggers harassment detection
  4. Email blocked for 1 hour (all IPs)
  5. Audit event: magic_link_request_velocity_violation (riskLevel: critical, reason: magic_link_harassment_attack)

Result: Victim receives max 4 magic link emails, protected from inbox spam.

Note: Audit event monitoring requires Business plan (auditLogsStatus = 'Active'). Free and Pro plans receive the security protection but not the audit trail visibility.

  1. login_velocity_violation (critical)

    • Indicates distributed attack in progress
    • Tenant should investigate if pattern repeats
    • Consider permanent lockout if sustained
  2. login_velocity_suspicious (high/medium)

    • Early warning of potential attack
    • May be false positive (user on mobile + VPN)
    • Monitor frequency over time
  3. login_geo_anomaly (high/medium)

    • User logged in from unexpected location
    • Could be legitimate (travel, VPN) or takeover
    • Review metadata: previous country, time since last login
  4. login_locked (high)

    • Account locked due to failed attempts
    • Check if lockoutCount > 3 (repeat offender)
    • Consider manual investigation

Critical Alert (immediate action):

  • 5+ login_velocity_violation events in 24 hours for different emails (coordinated attack)
  • Single email with 10+ login_locked events in 7 days (persistent targeting)

Warning Alert (review within 24 hours):

  • 20+ login_velocity_suspicious events in 1 hour (possible attack wave)
  • 10+ login_geo_anomaly events with riskLevel=high in 6 hours (mass account takeover attempt)

Info Alert (review weekly):

  • Any login_geo_anomaly for high-value accounts (admin users, premium customers)
  • login_locked events with lockoutCount >= 3 (repeat offenders)

Decision: Geo-anomaly detection logs to audit but doesn’t prevent login.

Rationale:

  • GeoIP data accuracy varies (70-95% depending on provider)
  • Users legitimately travel, use VPNs, mobile hotspots
  • False positives would frustrate legitimate users
  • Tenants have full audit logs to investigate and manually lock if needed

With these six layers of defense, Mindful Auth achieves enterprise-grade threat detection across all authentication surfaces without sacrificing user experience, available to all plan tiers.