El 26 de julio de 2026 Cloudflare me escribió un correo cortés para avisarme que estaba gastando más del doble de lo permitido. El tablero público del comando de bomberos voluntarios ya venía diciendo lo mismo a su manera, con menos cortesía: se caía a ratos. Un caché mal puesto escribía en cada visita, 2,400 escrituras diarias contra un límite de 1,000 al día.
El 25 de julio, un día antes, habíamos movido ese sitio del VPS al plan gratuito y yo dormía tranquilo: sin servidor que parchar, sin cron en una máquina que alguien tiene que recordar reiniciar. De cuánto estábamos consumiendo no tenía idea.
Cada recurso del plan tiene su propio límite
Yo pensaba el plan gratuito como un solo tanque y ahí estuvo mi error. Son bolsillos separados, cada uno con su límite: escrituras en KV (el almacén chico de llave y valor, 1,000 al día), invocaciones de Workers, filas leídas en D1, almacenamiento en R2, uso de Workers AI, cron triggers y minutos de GitHub Actions.
Funciona como un prepago con saldos separados. Te quedas sin datos y el celular ya no te sirve para ver por dónde viene la combi, aunque te sobren todos los minutos de llamada. Llenar un bolsillo tumba el sitio aunque los demás estén casi vacíos, y nosotros reventamos el más chico de todos.
El tablero cayéndose a ratos
Yo durmiendo tranquilo sin servidor que parchar
El medidor corre todos los días a la misma hora
Un script sin dependencias corre una vez al día en GitHub Actions: consulta el uso real de cada recurso y lo compara con su límite gratuito. Del 70% hacia arriba avisa; pasando el 90% hace fallar el build. En la misma corrida revisa que las páginas respondan y que los datos del tablero estén frescos.
Antes probamos un correo diario en rojo por un problema que ninguna automatización podía arreglar, y en una semana todos aprendimos a ignorarlo. Después probamos lo contrario, una advertencia silenciosa con el build en verde, que escondió el problema de cuota durante días. Ahora el estado vive en un issue de GitHub que se actualiza, en vez de un correo nuevo cada mañana.
La cuota siguió en 756 después de adivinar
Con el caché corregido, el medidor dejó las escrituras KV proyectadas en 756 de 1,000 al día. La explicación me salió en dos segundos: nos faltaban escrituras condicionales, escribir solo cuando el valor cambia. Fuimos al código y ya estaban implementadas desde antes. Adivinar me costó una tarde y la cuota siguió en 756, igual de firme.
Dos claves que nadie pidió nunca
Le pusimos medidor a cada caño en vez de abrir la pared: una línea de log por cada escritura a KV, y dejamos correr el sitio 19 minutos para ver cuál marcaba. En esa lista aparecieron dos claves de contabilidad interna, los cursores que marcan hasta dónde llegó cada scraper, y se llevaban el 30% de la cuota diaria. Ningún navegador las lee jamás.
Movimos los dos cursores a D1, la base SQL del mismo plan, que permite 100,000 escrituras al día. El mismo trabajo pasó del 30% de la cuota chica al 0.3% de la grande. Dejamos un test en CI, la revisión automática que corre con cada cambio, que falla si un cursor vuelve a KV, para que la lección no dependa de la memoria de nadie.
Lo que el medidor cuesta y lo que no resuelve
El medidor también gasta de un bolsillo: unos 2 minutos por corrida, cerca de 60 de los 2,000 minutos gratis de Actions al mes. Por esa misma cuenta, el scraper de Instagram quedó cada 30 minutos en vez de cada 15, y consume alrededor de 1,440 minutos al mes, el 72% de la cuota. Ese es el bolsillo más ajustado que nos queda y ya no le veo aire.
El medidor avisa y nada más. Si el tráfico del tablero crece de verdad, ningún script nos va a salvar: toca pagar o mover el trabajo a otro bolsillo.
Cuando algo consume de más, miro primero qué medidor está marcando, y no migramos nada sin su línea de log. Cloudflare no me ha vuelto a escribir, y el tablero tampoco se queja.
