Cuando arrancamos KEYON Access en producción en CBTis No. 001, la pregunta más común del director y subdirección administrativa fue: "¿cuánto vamos a pagar de Firebase al mes?". La respuesta honesta era "no sé hasta que veamos la realidad operativa". Este artículo es esa respuesta — seis meses de billing real con 700 alumnos, 580 padres con app instalada, 45,000 ingresos registrados, 130,000 push notifications enviados, 18 cloud functions activas. Incluye el bug de un día que triplicó la cuenta y las optimizaciones que la bajaron 60%. Útil si estás armando tu propio SaaS y quieres números, no estimaciones.

El proyecto: KEYON en producción

markdown
KEYON ACCESS — números operativos (abril 2026)
  Plantel:              CBTis No. 001 (Fresnillo, Zacatecas)
  Alumnos registrados:  700
  Padres con app:       580
  Ingresos / día:       ~1,400 (2 por alumno × 70% ingreso)
  Ingresos / mes:       ~30,000 - 35,000 eventos
  Push enviados / mes:  ~25,000 (FCM)
  Cloud Functions:      18 activas
  Firestore docs:       ~520,000 (alumnos + ingresos + sesiones + avisos)
  Storage usado:        2.3 GB (avatares + reportes PDF)

Stack: Firebase Spark → Blaze plan, proyecto en us-central1, Cloud Functions Node 22, firebase-admin v13, Firestore con 47 índices compuestos. Frontend Vite + Tailwind, app Android RN/Expo SDK 52.

El billing total de 6 meses

Cuentas mensuales reales en USD (aproximadas, antes de aplicar créditos de Google):

markdown
MES                   COSTO USD     COSTO MXN     EVENTOS / NOTAS
2025-11 (mes 1)       $4.20         ~$73          Setup, 50 alumnos pruebas
2025-12 (mes 2)       $11.80        ~$205         Onboarding 700 alumnos
2026-01 (mes 3)       $19.50        ~$338         Operación piloto, 30%
2026-02 (mes 4)       $52.40        ~$908         BUG (ver abajo) — un solo día
2026-03 (mes 5)       $24.60        ~$427         Post-fix, 100% operación
2026-04 (mes 6)       $19.10        ~$331         Post-optimización -60%

TOTAL 6 MESES:        $131.60       ~$2,282 MXN
PROMEDIO MENSUAL:     $21.93        ~$380 MXN
COSTO POR ALUMNO/MES: $0.031        ~$0.54 MXN

Antes del bug y post-optimización, KEYON cuesta menos de $20 USD al mes en Firebase. Por alumno por mes son ~$0.55 MXN — esencialmente ruido en cualquier operación escolar.

Firestore: el componente más caro

Firestore representa el ~70% de la cuenta. Los costos se desglosan en lecturas, escrituras, eliminaciones y storage. Ejemplo del mes 5 (operación normal):

markdown
FIRESTORE — abril 2026 (mes 6 post-optimización)

Lecturas:           4.2M reads / mes
  Costo:             ((4.2M - 50k free) × $0.06 / 100k) = $2.49 USD

Escrituras:          820k writes / mes
  Costo:             ((820k - 20k free) × $0.18 / 100k) = $1.44 USD

Deletes:             45k deletes / mes
  Costo:             ((45k - 20k free) × $0.02 / 100k) = $0.005 USD

Storage:             1.4 GB
  Costo:             1.4 × $0.18 / GB = $0.25 USD

Network egress:      8.2 GB
  Costo:             8.2 × $0.12 / GB = $0.98 USD

Total Firestore:     ~$5.16 USD ≈ $90 MXN

La métrica que más fácilmente se sale de control son las lecturas. Con 4.2M lecturas en un mes (que parece mucho) son $2.50 USD. Con 50M lecturas (10x) son $30 USD. La línea es lineal y predecible — pero el factor multiplicador depende de tu arquitectura.

De dónde salen las 4.2M lecturas

markdown
DESGLOSE DE LECTURAS (mes 6)

Panel admin (web)
  Listas de alumnos, paginadas:    900,000 reads
  Reportes mensuales (lazy):       320,000 reads
  Bitácora de eventos:             280,000 reads
  Subtotal panel:                  ~1.5M reads

App padres (Android)
  Listener "ingresos del día":     1,800,000 reads
  Listener "avisos":               420,000 reads
  Avatar de hijo (cache miss):     30,000 reads
  Subtotal app:                    ~2.25M reads

Cloud Functions (background)
  Triggers on document write:      180,000 reads
  Scheduled functions:             190,000 reads
  Subtotal functions:              ~370k reads

TOTAL:                              ~4.12M reads

La app de padres con su listener "ingresos del día" es el componente que más lee. Cada padre abre la app ~3 veces al día y deja un listener real-time que cuenta cada documento que matchea la query como una lectura.

El bug de un día que triplicó la cuenta

Mes 4 fue $52 USD vs $20 promedio. Causa: una Cloud Function deployada el 14 de febrero a las 10 AM tenía un bug en su listener recursivo. Cuando un documento `notificaciones/{padreId}/items` se creaba, el handler escribía un timestamp de "leído" que disparaba el mismo trigger. Loop infinito.

markdown
14 FEB 2026 — POST-MORTEM

10:00 AM    Deploy de notificarAsistencia v2 con escritura de readAt
10:15 AM    Primeros loops detectados en logs
14:00 PM    Padres reportan notificaciones duplicadas en app
15:30 PM    Diagnóstico: trigger recursivo sin guard
15:45 PM    Hotfix deployed (chequeo "if (after.readAt) return")
16:00 PM    Loop detenido tras 5h 45min

DAÑO:
  Functions invocations:      +3.2M de lo normal
  Firestore writes:           +4.1M
  Costo de ese día:           ~$32 USD (vs $0.65 normal)
  Mensajes FCM duplicados:    ~12k spam push

Lecciones del incidente:

1. Triggers de Firestore SIEMPRE necesitan guard de recursión

Cualquier handler `onWrite` o `onUpdate` que escribe al mismo documento debe verificar si la actualización vino del propio handler (campos "serverProcessed", "readAt", etc.) y retornar temprano. Cada escritura causa otro trigger.

2. Budget alerts en Cloud Console son esenciales

Configuramos un alert a $10 USD/día que ahora dispara email + WhatsApp al equipo. Con eso el bug se hubiera detectado a las 11 AM, no a las 3 PM.

3. Cloud Functions concurrency: limit por default

Por default v2 functions tienen concurrency 80 (80 requests en paralelo por instancia). En un loop, esto significa miles de ejecuciones por segundo. Bajar a `concurrency: 1` para functions críticas.

El cálculo del peor caso

El bug duró 5h 45min. Si hubiera durado 24 horas, habríamos quemado ~$130 USD en un solo día. Un loop infinito sin guard + Firestore + Functions sin budget alerts es uno de los pocos patterns en GCP donde puedes acumular miles de dólares en un fin de semana sin darte cuenta.

Las optimizaciones que bajaron 60% la cuenta

Después del bug rebalanceamos la app de padres. Estas tres optimizaciones bajaron de $52 USD del mes 4 a $19 del mes 6:

1. Reemplazar listeners real-time con polling cada 30s

Antes: cada app de padre tenía un listener `onSnapshot` activo mientras la app estaba abierta. Cada documento del query contaba como lectura cada vez que cambiaba. Costo: 1.8M reads/mes solo de la app.

Después: la app hace `getDocs` cada 30 segundos cuando está en foreground, y se apaga cuando va a background. Costo:280k reads/mes (-85%). El UX no cambió porque las notificaciones push siguen llegando vía FCM en tiempo real.

2. Paginación en panel admin

Antes: el listado de alumnos en el panel admin cargaba los 700 alumnos de un golpe. Cada visita = 700 reads. Costo:~900k reads/mes.

Después: paginación de 50 alumnos por página + búsqueda con index. Visita típica = 50 reads. Costo: 95k reads/mes (-89%).

3. Caché local de avatares en app padres

Antes: cada vez que la app cargaba la lista de hijos del padre, re-descargaba los avatares de Firestore Storage. Costo:1.2 GB egress/mes.

Después: usamos `react-native-fast-image` con cache permanente basado en hash del avatar. Costo: 180 MB egress/mes (-85%).

Otros componentes — desglose menor

Cloud Functions

markdown
FUNCTIONS — abril 2026

Invocations:         350k / mes
  Free tier:          2M / mes (gracias)
  Costo:              $0

CPU-seconds:         8,200 / mes (~2.3 hrs CPU)
  Free tier:          400,000 GHz-seconds
  Costo:              ~$0 (dentro del free tier)

Memory-seconds:      ~equivalente
  Costo:              $0

Egress (functions):  0.3 GB
  Costo:              $0.04

Total Functions:     ~$0.04 USD ≈ $1 MXN

Cloud Functions es prácticamente gratis para nuestra escala. El free tier de 2M invocaciones/mes cubre con creces la operación de un plantel. Solo se paga si tienes deltas de tráfico inusuales (caso del bug del mes 4).

Firebase Cloud Messaging

25,000 push notifications/mes. Costo: $0. Literalmente gratis ilimitado, incluso a millones de mensajes. Esto es lo que hace que un sistema escolar sea viable a costos chicos.

Authentication

1,400 usuarios activos mensuales (web + app + admins). Free tier aplica hasta 50,000 MAU para auth de phone/email. Costo: $0.

Hosting

Web admin con ~12 GB transfer/mes y storage de assets ~80 MB. Free tier cubre 10 GB transfer + 10 GB storage. Pagamos los 2 GB extras: ~$0.30 USD.

Para un SaaS escolar con 700 alumnos, Firebase cuesta lo mismo que un café por alumno por año. Es la categoría de gasto que ni aparece en el dashboard del director.

Si tuviéramos 10x usuarios

Pregunta natural: ¿esto escala lineal o se rompe? Estimación basada en patrones medidos:

markdown
ESCENARIO: 7,000 alumnos / 10 planteles / 5,800 padres con app

Firestore reads:           ~42M / mes
  Costo: ((42M - 50k) × $0.06 / 100k) = ~$25 USD

Firestore writes:          ~8.2M / mes
  Costo: ((8.2M - 20k) × $0.18 / 100k) = ~$15 USD

Functions invocations:     ~3.5M / mes (rebasa free tier)
  Costo: ((3.5M - 2M) × $0.40 / 1M) = ~$0.60 USD

Storage:                   ~14 GB
  Costo: ~$2.50 USD

Network egress:            ~80 GB
  Costo: ~$10 USD

Hosting:                   ~120 GB transfer
  Costo: ~$16.50 USD

FCM:                       250k mensajes / mes
  Costo: $0

TOTAL ESTIMADO:            ~$70 USD / mes ≈ $1,210 MXN
COSTO POR ALUMNO/MES:      ~$0.17 MXN

Escala razonablemente lineal con leve economía de escala (algunos costos fijos como Hosting, Storage). Para 10 planteles seguimos gastando < $1,500 MXN/mes en infraestructura.

Cuándo NO conviene Firebase

Firebase es óptimo para nuestra escala (700 - 7,000 alumnos). Hay tres escenarios donde la cuenta empezaría a doler:

1. Apps con queries complejos analíticos

Si necesitas joins, agregaciones SQL, GROUP BY, Firestore lo paga carísimo (cada documento leído = 1 read). Mejor BigQuery o PostgreSQL.

2. Volumen masivo de escrituras

Más de 50M writes/mes. A ese punto el costo Firestore por escritura se vuelve significativo y vale la pena un Cloud SQL o backend dedicado.

3. Real-time games / chats con miles de usuarios concurrentes

Cada listener real-time es un cliente con su propio canal. A 10k+ conexiones simultáneas, mejor algo basado en WebSockets dedicados.

Cierre

Firebase es uno de los mejores tradeoffs costo/beneficio para startups y proyectos institucionales en México. Para KEYON con 700 alumnos pagamos ~$20 USD/mes. La cuenta solo se sale de control si (a) tienes loops recursivos sin guard, (b) usas listeners real-time donde un poll cada 30s alcanza, o (c) cargas listas completas sin paginar. Las tres son fixes de horas, no de semanas.

Si estás armando un SaaS B2B y dudas si Firebase es el stack correcto, escríbenos en exara.uk/contacto con la descripción de tu caso (volumen esperado, tipo de queries, presupuesto target). En menos de 24 horas respondemos con una recomendación honesta — incluyendo cuándo Firebase es lo correcto y cuándo Supabase, PostgreSQL o algo más es la mejor opción.