DEV Community

Cover image for Rate limiting de una herramienta pública con Cloudflare KV y D1
Multita
Multita

Posted on

Rate limiting de una herramienta pública con Cloudflare KV y D1

Si tu producto tiene una parte gratis y pública, es cuestión de horas hasta que alguien la quiera exprimir con un script. Nosotros tenemos una consulta de multas gratis que cualquiera usa sin registrarse, así que el rate limiting no era opcional. Lo resolvimos entero en el borde, con Cloudflare KV y D1, sin servidor propio.

Quién hace qué

La división que nos funcionó es simple. KV guarda el contador, porque tiene TTL nativo y lecturas baratas en cada PoP. D1 (SQLite en el borde) guarda lo que sí querés conservar y cruzar después, como los leads del formulario.

const key = `rl:${ip}:${hoy}`;
const usado = parseInt(await env.RATE.get(key) || "0", 10);
if (usado >= LIMITE_DIARIO) return new Response("Probá mañana", { status: 429 });
await env.RATE.put(key, String(usado + 1), { expirationTtl: 86400 });
Enter fullscreen mode Exit fullscreen mode

El TTL de 86400 hace que la clave se borre sola al otro día. No limpiás nada, y el set de claves nunca crece más allá de "gente que consultó hoy".

La trampa de la consistencia

KV es eventualmente consistente, así que entre dos PoP hay una ventanita de un segundo donde alguien podría pasarse del límite. Para frenar abuso eso no me quita el sueño. Si necesitaras un límite estricto, con plata de por medio, ahí conviene un Durable Object, que te da consistencia fuerte a cambio de algo de latencia.

El límite como embudo

Un detalle de producto: el límite no es solo defensa, es conversión. Cuando alguien llega al tope, ese es el momento justo para ofrecerle el plan sin límite. El 429 deja de ser un error y pasa a ser una puerta.

Si vas a abrir algo gratis al público, poné el rate limiting desde el día uno. Sale mucho más barato que sacarte un scraper de encima después.



Enter fullscreen mode Exit fullscreen mode

Top comments (0)