VibeSecurity

Security check

Rate limiting: protecting login, OTP and paid API routes

Without limits, anyone can guess passwords, flood a one-time-password endpoint, or call a route that spends your money on every request. Rate limiting is cheap insurance against all three.

By the VibeSecurity team1 min read

Routes that need limits first

  • Login and password reset, to slow guessing.
  • OTP send and verify, to stop SMS pumping and code guessing.
  • Signup and contact forms, to cut spam.
  • Any route that calls a paid API such as an LLM, email or SMS provider.
  • Search or export endpoints that are expensive to compute.

Pick keys carefully

An IP-only limit is easy to bypass and can block many users behind one address. Combine IP with the account, email or phone number under attack, and use a shorter window for failed attempts.

A simple fixed-window limiter

This sketch uses a key-value store with expiry. Production code should use an atomic increment.

Pseudo-code
const key = `rl:${route}:${identity}:${Math.floor(Date.now() / windowMs)}`;
const count = await store.incr(key);
if (count === 1) await store.expire(key, windowSeconds);
if (count > limit) {
  return new Response('Too many requests', {
    status: 429,
    headers: { 'Retry-After': String(windowSeconds) },
  });
}

Also limit at the edge

Your host or CDN can throttle traffic before it reaches your code. Use that for blunt protection and keep account-aware limits in the app.

Frequently asked questions

What limit should I choose?

Start strict for sensitive routes, for example a handful of login attempts per account per few minutes, then loosen based on real usage.

Is a CAPTCHA a replacement?

It helps against bots on forms but does not cap volume. Use it together with limits.

Sources

  1. 1.OWASP API Security: Unrestricted Resource Consumption