# Diseño de On-Call — Guía de Operaciones Sostenibles

El on-call sostenible no es sobre resistencia individual al cansancio —
es sobre diseñar el sistema para que los incidentes sean manejables,
raros y de corta duración. Un buen programa de on-call mide su éxito
en la reducción de alertas, no en la tolerancia a ellas.

---

## Estructura de rotación

### Modelo primario + secundario

El modelo más robusto para equipos medianos (5–15 personas):

```
Primario   — Primera línea de respuesta. Responde dentro de 5 minutos en P1.
Secundario — Respaldo si el primario no responde en 10 minutos o necesita ayuda.
Escalación — Tech Lead o arquitecto. Solo para P1 sin resolución en 30 minutos.
```

**Duración recomendada por turno**:
- Semanal (lunes a lunes) para equipos con < 8 ingenieros.
- Quincenal para equipos con ≥ 8 ingenieros — reduce la frecuencia de guardia.

La semana quincenal (14 días) reduce la carga sin aumentar el riesgo si el
runbook y el sistema de escalación están bien configurados.

### Ejemplo de configuración en PagerDuty / OpsGenie

```yaml
# Estructura de escalación en OpsGenie
escalation_policy:
  name: "API de Producción"
  rules:
    - condition: match-all
      notify_type: default
      delay: 0
      recipients:
        - type: schedule
          id: "primario-semana"     # primero al on-call primario
    - condition: match-all
      notify_type: default
      delay: 10                      # si no responde en 10 min
      recipients:
        - type: schedule
          id: "secundario-semana"   # al secundario
    - condition: match-all
      notify_type: default
      delay: 30                      # si tampoco responde en 30 min
      recipients:
        - type: user
          username: "tech-lead"     # al tech lead
```

### Horario de guardia mínimo viable

Para equipos pequeños (3–5 personas) que no pueden cubrir 24/7 sin quemarse,
una opción es on-call **solo en horario extendido** (ej: 7am–11pm) con SLA
de respuesta de 4 horas fuera de ese horario. Esta opción requiere negociación
explícita con clientes o stakeholders sobre las expectativas de disponibilidad.

---

## Herramientas: PagerDuty vs OpsGenie

| Característica | PagerDuty | OpsGenie |
|----------------|-----------|----------|
| Integración con Prometheus | Sí (vía Alertmanager) | Sí (nativa) |
| Schedules con overrides | Sí | Sí |
| App móvil | Sí | Sí |
| On-call scheduling visual | Excelente | Bueno |
| Precio (inicio) | Desde $21/usuario/mes | Desde $9/usuario/mes |
| API para automatización | REST completa | REST completa |

### Configuración básica de Alertmanager → PagerDuty

```yaml
# alertmanager.yml
receivers:
  - name: "pagerduty-critico"
    pagerduty_configs:
      - routing_key: "<INTEGRATION_KEY>"
        severity: critical
        description: "{{ .CommonAnnotations.summary }}"
        details:
          runbook: "{{ .CommonAnnotations.runbook }}"
          dashboard: "{{ .CommonAnnotations.dashboard }}"

  - name: "pagerduty-advertencia"
    pagerduty_configs:
      - routing_key: "<INTEGRATION_KEY_WARNING>"
        severity: warning

route:
  receiver: "pagerduty-critico"
  routes:
    - match:
        severity: warning
      receiver: "pagerduty-advertencia"
    - match:
        severity: critical
      receiver: "pagerduty-critico"
```

---

## Fatiga de alertas: métricas y diagnóstico

La fatiga de alertas es el estado donde el equipo de on-call empieza a ignorar
alertas porque hay demasiadas y demasiados falsos positivos. Es uno de los
problemas más peligrosos porque silencia el sistema de detección de incidentes
justo cuando más se necesita.

### Métricas de salud del on-call

Medir semanalmente:

| Métrica | Definición | Umbral de preocupación |
|---------|------------|----------------------|
| **Alertas por semana** | Total de alertas que despertaron al on-call | > 10/semana por ingeniero |
| **MTTA** (Mean Time to Acknowledge) | Tiempo promedio hasta reconocer la alerta | > 5 minutos en P1 |
| **MTTR** (Mean Time to Resolve) | Tiempo promedio hasta resolver el incidente | Depende del SLO; registrar tendencia |
| **Ratio de falsos positivos** | Alertas que no requerían acción / total | > 30% es señal de alarma |
| **Alertas fuera de horario laboral** | Alertas entre 11pm y 7am | > 2/semana es insostenible |

```bash
# Script básico para contar alertas en PagerDuty (últimos 7 días)
curl -s "https://api.pagerduty.com/incidents" \
  -H "Authorization: Token token=<TOKEN>" \
  -H "Accept: application/vnd.pagerduty+json;version=2" \
  -G \
  --data-urlencode "since=$(date -d '7 days ago' -Iseconds)" \
  --data-urlencode "until=$(date -Iseconds)" | \
  jq '.total'
```

### Diagnóstico de alertas ruidosas

Si el número de alertas supera el umbral, ejecutar este análisis:

```bash
# Identificar las alertas que más despiertan al on-call
# (requiere acceso a Alertmanager o la API de tu herramienta)
# El objetivo: las 3 alertas más frecuentes son las candidatas a mejorar primero
```

Preguntas de diagnóstico para cada alerta frecuente:
1. ¿Cuántas veces en el último mes requirió acción humana real? (no solo acknowledging)
2. ¿El runbook resuelve el problema en < 15 minutos?
3. ¿Se podría automatizar la mitigación?
4. ¿El umbral está bien calibrado o genera falsos positivos?

---

## La regla de los 5 minutos

Si el ingeniero de guardia no puede entender el problema y tomar una primera
acción de mitigación en 5 minutos, el runbook está incompleto.

Checklist de runbook bien escrito:
- [ ] La primera sección dice exactamente qué verificar (con comandos copiables).
- [ ] Hay una acción de mitigación rápida aunque no resuelva la causa raíz (ej: rollback, reinicio).
- [ ] El dashboard relevante tiene un enlace directo en el runbook.
- [ ] Los criterios de escalación son claros y no ambiguos.

Si un runbook falla la regla de los 5 minutos en un incidente real, actualizarlo
es la primera acción del post-mortem.

---

## Compensación y sostenibilidad

El on-call no es trabajo gratuito. Los equipos que no reconocen explícitamente
la carga del on-call tienen alta rotación y queman a sus mejores ingenieros.

### Modelos de compensación

| Modelo | Descripción | Recomendación |
|--------|-------------|---------------|
| Tiempo compensatorio | Día libre por guardia nocturna activa | Mínimo aceptable |
| Compensación económica | Pago adicional por hora de guardia activa fuera de horario | Más justo |
| Tiempo libre por rotación | Semana de guardia = semana sin reuniones | Complemento útil |

### Señales de que el on-call no es sostenible

- Ingenieros buscan excusas para salir de la rotación.
- Las alertas fuera de horario superan 2 por semana de manera sostenida.
- El MTTR está aumentando (el equipo se cansa y resuelve más lento).
- Los post-mortems muestran errores de fatiga (decisiones tomadas a las 3am).

Cuando se detectan estas señales, el problema no es "necesitamos más ingenieros
en on-call" — es "necesitamos reducir el número de incidentes y mejorar
la automatización de respuesta".

---

## Proceso de incorporación al on-call (shadowing)

Un ingeniero nuevo nunca debe entrar directamente a la rotación de primario.
El proceso de incorporación estándar:

1. **Semana 1–2**: observar (shadow) la guardia del primario sin responsabilidad.
2. **Semana 3–4**: ser secundario con el primario disponible para apoyo inmediato.
3. **Semana 5+**: primario con secundario de apoyo normal.

Prerequisitos antes de la primera guardia como primario:
- [ ] Conocer todos los servicios en la rotación y sus dependencias.
- [ ] Haber leído todos los runbooks de P1 y P2.
- [ ] Haber participado en al menos un post-mortem.
- [ ] Tener acceso verificado a las herramientas de producción.

---

## Plantilla de reporte semanal de on-call

```markdown
## Reporte On-Call — Semana [N] — [fechas]
**Ingeniero primario**: [nombre]
**Ingeniero secundario**: [nombre]

### Resumen de alertas
- Total de alertas: [N]
- Alertas fuera de horario laboral: [N]
- Falsos positivos: [N] ([X%])
- Incidentes P1: [N]
- Incidentes P2: [N]

### MTTA promedio: [N minutos]
### MTTR promedio: [N minutos]

### Acciones recomendadas
- [ ] Ajustar umbral de [alerta X] — se activó [N] veces sin requerir acción
- [ ] Actualizar runbook de [alerta Y] — tomó más de 15 minutos resolver
- [ ] Automatizar [tarea Z] — se ejecutó manualmente [N] veces esta semana
```
