Los incidentes sin barreras de seguridad se repiten. Las barreras de seguridad son alertas, pruebas, reglas de linting y listas de verificación que hacen que el mismo fallo sea más difícil o visible antes. Los equipos de Python las codifican en pytest, Ruff, revisión de Alembic y alertas de consumo de SLO.
Tarjeta de receta de referencia rápida, lista para copiar y pegar.
# Regresión de pytest del post-mortem INC-8842def test_migration_uses_concurrently_for_large_tables(): sql = Path("alembic/versions/20260612_add_invoice_idx.py").read_text() assert "CONCURRENTLY" in sql or "op.create_index" not in sql
# Alerta: Indicador principal de profundidad de la cola de Celery- alert: BillingQueueDepthHigh expr: celery_queue_length{queue="billing"} > 10000 for: 5m
Cuándo usar esto:
Los elementos de acción del post-mortem necesitan una entrega concreta
La misma clase de incidente ocurrió dos veces en un trimestre
La auditoría solicita controles preventivos
Fatiga de guardia debido a páginas ruidosas pero prevenibles
"""guardrails_example.py - pruebas impulsadas por incidentes y verificaciones en tiempo de ejecución."""from __future__ import annotationsfrom dataclasses import dataclassfrom pathlib import Path@dataclass(frozen=True)class Guardrail: incident_id: str kind: str # test | alert | lint | runbook description: str verify: strGUARDRAILS: list[Guardrail] = [ Guardrail( incident_id="INC-8842", kind="test", description="Los índices de tablas grandes usan CONCURRENTLY", verify="pytest tests/test_migrations.py -k concurrently", ), Guardrail( incident_id="INC-9011", kind="alert", description="Tasa de consumo de P95 del checkout", verify="Grafana: CheckoutSLOBurn", ), Guardrail( incident_id="INC-9011", kind="lint", description="No hay sleep síncrono en rutas asíncronas", verify="scripts/check_async_blocking.py en CI", ),]def audit_open_guardrails(registry: list[Guardrail]) -> None: for g in registry: print(f"[{g.incident_id}] {g.kind}: {g.description} -> {g.verify}")if __name__ == "__main__": audit_open_guardrails(GUARDRAILS)
# tests/test_incident_9011_loop_block.pyimport astfrom pathlib import Pathdef test_no_time_sleep_in_async_functions(): src = Path("src/api/routes/checkout.py").read_text() tree = ast.parse(src) for node in ast.walk(tree): if isinstance(node, ast.AsyncFunctionDef): for child in ast.walk(node): if isinstance(child, ast.Call): func = child.func if isinstance(func, ast.Attribute) and func.attr == "sleep": raise AssertionError(f"time.sleep en async {node.name}")
Lo que esto demuestra:
Las barreras de seguridad se vinculan a los IDs de incidentes para trazabilidad
Las pruebas de regresión codifican mecánicas de fallo específicas
Los scripts de CI detectan patrones de bloqueo asíncrono
La revisión de operaciones audita los comandos de verificación, no solo el cierre de tickets
Elementos de acción que dicen "sé más cuidadoso" - No son barreras de seguridad. Solución: Requerir una prueba, alerta o verificación automatizada por elemento.
Alertas sin enlace a runbook - El guardia ignora el ruido. Solución: La anotación apunta a los pasos de mitigación.
Pruebas que simulan el error - La regresión nunca falla. Solución: Probar en el límite de integración que falló en producción.
Barreras de seguridad en un solo servicio - El equipo hermano repite el incidente. Solución: La plataforma promueve el patrón al repositorio de plantillas.
Cerrar tickets sin verificación - La deriva regresa. Solución: La revisión de operaciones mensual ejecuta el comando verify del registro.