RUNBOOK

Plan Sync API — Respuesta a Incidentes

Servicio: Plan Sync API v2
Equipo: Backend / DevOps
Canal: #nutriflow-incidents
PagerDuty: nutriflow-oncall
Última revisión: 2026-06-16
Owner: @platform-team
Node.js · Kubernetes · PostgreSQL 15
api.nutriflow.io/v2/plans
RDS · Redis · SendGrid · AWS S3
1 Niveles de Severidad
SEV1
Caída total
0% de sincronizaciones funcionan. Todas las empresas clientes afectadas. Pérdida de datos posible.
Responder en 15 min
SEV2
Degradación mayor
Tasa de error >10%. Feature crítica rota (sincronización de planes diarios).
Responder en 30 min
SEV3
Impacto menor
Funcionalidad no crítica degradada. Informes PDF lentos, emails retrasados.
Responder en 2 h
SEV4
Impacto mínimo
Bug estético, link roto, dato menor desactualizado. Sin impacto operativo.
Siguiente día hábil
2 Checklist Rápido — Para leer con 3 AM de sueño
⚡ Ejecutar en orden. No saltes pasos.
1. Declarar severidad y abrir war-room en Slack→ #nutriflow-incidents
2. Comprobar salud del servicio (pods + health endpoint)→ Sección 4.1
3. Revisar deploys recientes (últimas 2 horas)→ Sección 4.1
4. Si hay deploy sospechoso → rollback inmediato→ Sección 6
5. Publicar notificación inicial en #nutriflow-incidents→ Sección 7
6. Comprobar DB: conexiones, queries lentas, lag replica→ Sección 4.2
7. Verificar dependencias externas (Redis, SendGrid, S3)→ Sección 4.3
8. Si >15 min sin resolución SEV1/SEV2 → escalar→ Sección 8
9. Confirmar resolución con smoke-test→ Sección 5
10. Publicar mensaje de RESOLVED y agendar postmortem→ Sección 7
3 Triaje Inicial — Primeros 5 minutos
Síntoma observado Causa probable Acción
Todas las peticiones fallan (500/503) Servicio caído / pod crash-looping → Sección 4.1
Latencia p99 > 3s, timeout errors DB saturada / dependencia externa lenta → Sección 4.2
Fallos en endpoints específicos (e.g. /plans/sync) Bug en código / datos corruptos → Sección 4.3
Spike de tráfico repentino >5x normal Cron masivo de clientes / posible ataque → Sección 4.4
Health check inicial BASH
# 1. Verificar pods en el namespace
kubectl get pods -n nutriflow -l app=plan-sync-api

# 2. Comprobar deploys recientes
kubectl rollout history deployment/plan-sync-api -n nutriflow

# 3. Ping al health endpoint
curl -I https://api.nutriflow.io/v2/plans/health

# 4. Tasa de error actual (Prometheus)
curl -s "http://prometheus:9090/api/v1/query?query=sum(rate(http_requests_total{status=~'5..',service='plan-sync'}[5m]))" | jq '.data.result[0].value[1]'
4 Procedimientos de Mitigación
4.1 Servicio Completamente Caído SEV1
Diagnóstico y recuperación de podsBASH
# Paso 1: Ver estado de pods
kubectl get pods -n nutriflow

# Paso 2: Si pods en CrashLoopBackOff → revisar logs
# Prereq: kubectl configurado, kubeconfig → cluster prod
# Si falla: aws eks update-kubeconfig --name nutriflow-prod --region eu-west-1
kubectl logs -n nutriflow -l app=plan-sync-api --tail=100

# Paso 3: Revisar historial de deploys
kubectl rollout history deployment/plan-sync-api -n nutriflow

# Paso 4: ROLLBACK si el deploy reciente es sospechoso
kubectl rollout undo deployment/plan-sync-api -n nutriflow

# Paso 5: Escalar réplicas si hay limitación de recursos
kubectl scale deployment/plan-sync-api -n nutriflow --replicas=8

# Paso 6: Verificar recuperación
kubectl rollout status deployment/plan-sync-api -n nutriflow
4.2 Alta Latencia / Timeouts SEV2
ADVERTENCIA: Los comandos pg_terminate_backend terminan conexiones activas. Verifica el número de conexiones antes de ejecutar.
Diagnóstico de base de datosSQL
-- DRY RUN: Contar conexiones idle largas antes de terminar
SELECT count(*)
FROM pg_stat_activity
WHERE state = 'idle'
  AND query_start < now() - interval '10 minutes';

-- Queries lentas activas
SELECT pid, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active'
  AND duration > interval '5 seconds'
ORDER BY duration DESC;

-- EJECUTAR solo si count es < 50
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
  AND query_start < now() - interval '10 minutes';
Circuit breaker RedisBASH
# Si Redis está saturado, activar circuit breaker
kubectl set env deployment/plan-sync-api \
  REDIS_CIRCUIT_BREAKER_ENABLED=true \
  REDIS_FALLBACK_MODE=passthrough \
  -n nutriflow

# Verificar latencia de dependencias externas
curl -w "Time: %{time_total}s\n" -o /dev/null -s https://api.sendgrid.com/v3/health
4.3 Fallos Parciales — Endpoints Específicos SEV2 / SEV3
Identificar patrón de erroresBASH
# Agrupar errores por tipo
kubectl logs -n nutriflow -l app=plan-sync-api --tail=500 | \
  grep -i error | sort | uniq -c | sort -rn | head -20

# Deshabilitar feature problemática via flag
curl -X POST https://api.nutriflow.io/internal/feature-flags \
  -H "Authorization: Bearer $INTERNAL_TOKEN" \
  -d '{"flag": "SYNC_BULK_MODE", "enabled": false}'

# Revisar cambios recientes en datos
Auditoría de datos recientesSQL
SELECT *
FROM audit_log
WHERE table_name = 'nutrition_plans'
  AND created_at > now() - interval '1 hour'
ORDER BY created_at DESC;
4.4 Pico de Tráfico Repentino SEV2
Escalar y protegerBASH
# Ver consumo actual de pods
kubectl top pods -n nutriflow

# Escalar horizontalmente
kubectl scale deployment/plan-sync-api -n nutriflow --replicas=16

# Activar rate limiting
kubectl set env deployment/plan-sync-api \
  RATE_LIMIT_ENABLED=true \
  RATE_LIMIT_RPS=500 \
  -n nutriflow

# Si se sospecha ataque DDoS → aplicar NetworkPolicy
kubectl apply -f network-policy-block-suspicious.yaml
5 Verificación & Smoke Test
Confirmar recuperación completaBASH
# Health check del servicio
curl -s https://api.nutriflow.io/v2/plans/health | jq

# Tasa de error debe estar < 1%
curl -s "http://prometheus:9090/api/v1/query?query=sum(rate(http_requests_total{status=~'5..',service='plan-sync'}[5m]))" | jq

# Latencia p99 debe estar < 500ms
curl -s "http://prometheus:9090/api/v1/query?query=histogram_quantile(0.99,sum(rate(http_request_duration_seconds_bucket{service='plan-sync'}[5m]))by(le))" | jq

# Smoke test de flujo crítico: crear plan → sincronizar → validar
./scripts/smoke-test-plan-sync.sh
6 Procedimientos de Rollback
Rollback completoBASH
# Rollback del deployment Kubernetes
kubectl rollout undo deployment/plan-sync-api -n nutriflow

# Rollback de migración de DB (si aplica)
./scripts/db-rollback.sh $MIGRATION_VERSION

# Desactivar feature flag recién desplegada
curl -X POST https://api.nutriflow.io/internal/feature-flags \
  -d '{"flag": "NEW_SYNC_ENGINE_V2", "enabled": false}'

# Verificar que la versión anterior está corriendo
kubectl describe deployment/plan-sync-api -n nutriflow | grep Image
7 Plantillas de Comunicación
INVESTIGATING Notificación inicial — Slack #nutriflow-incidents
🚨 INCIDENT: Plan Sync API Degradada Severity: SEV2 Status: Investigating Impact: ~15% de sincronizaciones fallando (~230 empresas afectadas) Inicio: [HH:MM UTC] Incident Commander: [NOMBRE] Acciones actuales: - Revisando logs y métricas - Comprobando deploys recientes - Monitorizando dashboards Grafana Próxima actualización en #nutriflow-incidents en 15 min.
MITIGATING Actualización de estado — cada 15 minutos
📊 UPDATE: Plan Sync API — Incidente activo Status: Mitigating Impact: Reducido a ~3% de fallos Duración: 22 min Acciones tomadas: - Rollback deployment v1.9.2 → v1.9.1 - Escalado de 4 → 10 réplicas Próximos pasos: - Monitorizando estabilidad - Análisis de causa raíz en progreso ETA resolución: ~10 min Próximo update: en 15 min aunque no haya novedades.
RESOLVED Notificación de resolución
✅ RESOLVED: Plan Sync API — Incidente cerrado Duración total: 38 minutos Impacto: ~1.800 sincronizaciones fallidas (reintentadas automáticamente) Causa raíz: Memory leak introducido en v1.9.2 bajo carga sostenida Resolución: - Rollback a v1.9.1 (estable) - Sincronizaciones pendientes procesadas por cola de reintentos Seguimiento: - Postmortem programado: 2026-06-17 10:00 - Fix en desarrollo: issue #847 - Revisión del pipeline de deploy: pendiente
8 Matriz de Escalado
Condición Escalar a Contacto Canal
SEV1/SEV2 >15 min sin resolver Lead Backend @lead-backend Slack + llamada
SEV1 >30 min sin resolver Head of Engineering @head-eng PagerDuty
Impacto en datos de salud de empleados CTO + Legal @cto #security-incidents
Impacto económico >5.000€ CEO + Finance @finance-oncall Llamada directa
Comunicación a clientes necesaria Customer Success Lead @cs-lead Slack directo
Principios de escalado:
  • Escalar pronto, no tarde. El orgullo cuesta más tiempo que la llamada.
  • Asignar un Incident Communicator separado del IC para gestionar updates.
  • Nunca trabajar solo en un SEV1. Pedir al menos un segundo par de ojos.
  • Documenta en tiempo real en el hilo de Slack: cada acción con timestamp.