Korzen

Blog

Fail-open: por qué una verificación de bots nunca debe tirar tu sitio

Una verificación de bots está delante de tus páginas más valiosas. Si falla cerrada, su caída es tu caída. Cómo llamarla de forma que solo pueda mejorar las cosas.

Una verificación de bots está en las páginas que más importan: el login, el registro, el checkout. Eso es lo que la hace útil, y también lo que la hace peligrosa. Si cada checkout la espera, el día que esté lenta tu checkout estará lento; el día que se caiga, te caes tú también.

Fail-open, fail-closed

Cuando la verificación no puede responder, hay dos opciones. Fail-closed bloquea al visitante: seguro contra bots, fatal para el negocio, porque también se bloquea a cada cliente real. Fail-open deja pasar al visitante: durante la caída, los bots entran como entraban antes de que tuvieras una verificación, y nadie más lo nota.

Para casi cualquier sitio, fail-open es lo correcto. Unos minutos sin protección contra bots cuestan poco; unos minutos sin checkout cuestan mucho, y además la confianza de quien lo vio.

Cuatro reglas para llamar a una verificación de bots

  1. Un timeout corto. Elige lo máximo que aceptas sumarle a la página, de 100 a 200 ms, e imponlo en tu código. Nunca dependas de que el otro lado sea rápido.
  2. Cualquier error deja pasar al visitante. Un timeout, un error de conexión, un 5xx, un 402 por plan agotado o una respuesta que no puedes leer: todo significa "sin respuesta", y sin respuesta significa seguir adelante.
  3. Actúa solo con una respuesta segura. Bloquea en la clase de bot más alta; con evidencia más débil, suma fricción, como un código por email, nunca un muro.
  4. Registra lo que falló. Cuenta los timeouts y los errores, para que una caída sea un gráfico, no un misterio.

Cómo se ve en el código

const d = await fetch(API + "/v1/decide", {
  method: "POST",
  headers: { Authorization: `Bearer ${KEY}` },
  body: JSON.stringify({ ip, user_agent, token, path }),
  signal: AbortSignal.timeout(150),
}).then((r) => r.json()).catch(() => null);

if (d?.class === "bot_high") return res.status(403).end();
// cualquier otra cosa, incluso sin respuesta: sigue adelante

El catch es toda la política: lo que salga mal se vuelve null, y null nunca es un bot.

El lado del navegador también es fail-open

El script en tu página tampoco debe frenarla nunca. Si no puede hablar con el servicio, la página funciona exactamente como funcionaría sin él; la decisión del servidor simplemente tiene menos evidencia esa vez.

Cómo lo resuelve Bot Protection

Bot Protection es una llamada desde tu servidor, no un proxy delante de tu sitio, así que nunca está en el camino de una solicitud que no elegiste verificar. Su tag espera un tiempo limitado y, si no hay respuesta, desiste sin hacer ruido. En tu límite de gasto responde 402, que tu código trata como cualquier otro error: los visitantes pasan, y recibes un email antes de que ocurra.