Aprende a diseñar y construir una app web que rastree el cumplimiento de SLA: definir métricas, colectar eventos, calcular resultados, alertar sobre incumplimientos y generar informes auditables.

El cumplimiento de SLA significa cumplir las promesas medibles en un Service Level Agreement (SLA): un contrato entre proveedor y cliente. La tarea de tu app es responder una pregunta simple con evidencia: ¿Cumplimos lo prometido, para este cliente, durante este periodo?
Conviene separar tres términos relacionados:
La mayoría de apps de seguimiento de SLA empiezan con un pequeño conjunto de métricas que se mapean a datos operativos reales:
Diferentes usuarios quieren la misma verdad, presentada de forma distinta:
Este producto trata sobre seguimiento, evidencia e informes: colectar señales, aplicar reglas acordadas y generar resultados aptos para auditoría. No garantiza rendimiento; lo mide—con precisión, consistencia y de forma que puedas defender más tarde.
Antes de diseñar tablas o escribir código, aclara dolorosamente qué significa “cumplimiento” para tu negocio. La mayoría de los problemas de seguimiento de SLA no son técnicos—son problemas de requisitos.
Empieza por recoger las fuentes de verdad:
Escribe estas reglas de forma explícita. Si una regla no puede enunciarse claramente, no puede calcularse de forma fiable.
Lista las “cosas” del mundo real que pueden afectar un número de SLA:
También identifica quién necesita qué: soporte quiere riesgo de incumplimiento en tiempo real, managers quieren resúmenes semanales, clientes quieren resúmenes simples (a menudo para una página de estado).
Mantén el alcance pequeño. Elije el conjunto mínimo que demuestre que el sistema funciona de extremo a extremo, por ejemplo:
Crea una hoja de una página que puedas probar más tarde:
Éxito: dos personas calculan manualmente el mismo mes de ejemplo y tu app coincide exactamente.
Un rastreador de SLA correcto empieza con un modelo de datos que pueda explicar por qué un número es lo que es. Si no puedes trazar una cifra de disponibilidad mensual hasta los eventos exactos y las reglas usadas, tendrás disputas con clientes e incertidumbre interna.
Como mínimo, modela:
Una relación útil: customer → service → SLA policy (posiblemente vía plan). Incidentes y eventos referencian el servicio y el cliente.
Los errores temporales son la causa #1 de mala aritmética SLA. Almacena:
occurred_at como UTC (timestamp con semántica de zona horaria)received_at (cuando tu sistema lo vio)source (nombre del monitor, integración, manual)external_id (para deduplicar reintentos)payload (JSON bruto para depuración futura)También guarda customer.timezone (cadena IANA como America/New_York) para mostrar y para la lógica de “horario laboral”, pero no la uses para reescribir el tiempo del evento.
Si los SLA de tiempo de respuesta se pausan fuera del horario laboral, modela calendarios explícitos:
working_hours por cliente (o por región/servicio): día de la semana + hora inicio/finholiday_calendar ligado a una región o cliente, con rangos de fechas y etiquetasMantén las reglas dirigidas por datos para que ops puedan actualizar un festivo sin desplegar código.
Almacena eventos crudos en una tabla append-only y guarda resultados calculados por separado (p. ej., sla_period_result). Cada fila de resultado debe incluir: límites del periodo, versión de entradas (versión de la política + versión del motor), y referencias a los IDs de eventos usados. Esto hace que la recomputación sea segura y te da una traza de auditoría cuando los clientes preguntan “¿Qué minutos de caída contaste?”.
Los números SLA son tan confiables como los eventos que ingieres. El objetivo es simple: capturar cada cambio que importe (inicio de caída, incidente reconocido, servicio restaurado) con timestamps consistentes y contexto suficiente para calcular cumplimiento más tarde.
La mayoría de equipos acaban tirando de una mezcla de sistemas:
Webhooks suelen ser lo mejor para precisión en tiempo real y menor carga: el sistema origen empuja eventos a tu endpoint.
Polling es un buen respaldo cuando no hay webhooks: tu app busca periódicamente cambios desde el último cursor. Necesitarás manejo de rate limits y lógica cuidadosa de “since”.
Importación CSV ayuda con backfills y migraciones. Trátala como camino de ingesta de primera clase para poder reprocesar periodos históricos sin hacks.
Normaliza todo en una única forma interna de “evento”, incluso si los payloads upstream difieren:
event_id (required): único y estable ante reintentos. Prefiere el GUID del origen; si no, genera un hash determinístico.source (required): p. ej., datadog, servicenow, manual.event_type (required): p. ej., incident_opened, incident_acknowledged, service_down, service_up.occurred_at (required): el momento en que ocurrió el evento (no cuando lo recibiste), con zona horaria.received_at (system): cuando tu app lo ingirió.service_id (required): el servicio relevante para el SLA que afecta.incident_id (opcional pero recomendado): enlaza múltiples eventos a un incidente.attributes (opcional): prioridad, región, segmento de cliente, etc.Guarda event_id con una restricción única para hacer la ingesta idempotente: los reintentos no crearán duplicados.
Rechaza o cuarentena eventos que:
occurred_at muy en el futuro.service_id conocido (o requieran un flujo explícito “unmapped”).event_id existente.Esta disciplina al inicio te ahorra discutir informes SLA después—porque podrás apuntar a entradas limpias y trazables.
Tu motor de cálculo es donde los “eventos crudos” se convierten en resultados de SLA defendibles. La clave es tratarlo como contabilidad: reglas deterministas, entradas claras y un rastro reproducible.
Convierte todo en un único flujo ordenado por incidente (o por impacto de servicio):
Desde esta línea temporal, calcula duraciones sumando intervalos, no restando dos timestamps a ciegas.
Define TTFR como el tiempo transcurrido “cobrable” entre incident_start y first_agent_response (o acknowledged, según el texto del SLA). Define TTR como el tiempo transcurrido “cobrable” entre incident_start y resolved.
“Cobrable” significa quitar intervalos que no deben contarse:
Detalle de implementación: almacena una función calendario (horario laboral, festivos) y una función de reglas que tome una línea temporal y devuelva intervalos facturables.
Decide desde el inicio si calculas:
Para caídas parciales, pondera por impacto solo si el contrato del SLA lo requiere; de lo contrario trata “degradado” como una categoría de incumplimiento separada.
Cada cálculo debe ser reproducible. Persiste:
Cuando las reglas cambien, podrás volver a ejecutar cálculos por versión sin reescribir la historia—crucial para auditorías y disputas con clientes.
Los informes son donde el seguimiento de SLA gana o pierde confianza. Tu app debe dejar claro qué rango temporal se mide, qué minutos cuentan y cómo se derivaron los números finales.
Da soporte a los periodos de informe que los clientes realmente usan:
Almacena periodos como timestamps explícitos de inicio/fin (no “mes = 3”) para poder reproducir cálculos después.
Una fuente frecuente de confusión es si el denominador es todo el periodo o solo el tiempo “elegible”.
Define dos valores por periodo:
Luego calcula:
availability_percent = 100 * (eligible_minutes - downtime_minutes) / eligible_minutes
Si minutos elegibles puede ser cero (p. ej., un servicio monitoreado solo en horario laboral y el periodo no contiene ninguno), define la regla por adelantado: “N/A” o tratarlo como 100%—pero sé consistente y documenta.
La mayoría de SLAs necesitan tanto un porcentaje como un resultado binario.
También conserva la “distancia al incumplimiento” (presupuesto de downtime restante) para que los dashboards puedan avisar antes de cruzar el umbral.
Finalmente, conserva los inputs crudos (eventos incluidos/excluidos y ajustes) para que cada informe pueda responder “¿por qué es este número?” sin rodeos.
Tu motor de cálculo puede ser perfecto y aún así fallar a los usuarios si la UI no responde la pregunta básica: “¿Estamos cumpliendo el SLA ahora y por qué?” Diseña la app para que cada pantalla empiece con un estado claro y luego permita profundizar en los números y en los eventos crudos que los generaron.
Dashboard overview (para operadores y managers). Lidera con un conjunto pequeño de tiles: cumplimiento del periodo actual, disponibilidad, cumplimiento de tiempos de respuesta y “tiempo restante antes del incumplimiento” cuando aplique. Usa etiquetas explícitas (p. ej., “Disponibilidad (este mes)” en vez de “Uptime”). Si soportas múltiples SLAs por cliente, muestra primero el peor estado y permite expandir.
Detalle del cliente (para equipos de cuentas y reportes al cliente). Una página de cliente debe resumir todos los servicios y niveles SLA para ese cliente, con un estado simple aprobado/advertencia/fallido y una explicación corta (“2 incidentes contados; 18m de downtime contados”). Añade enlaces a /status (si proporcionas una página de estado para clientes) y a la exportación del informe.
Detalle del servicio (para investigación profunda). Aquí muestra las reglas SLA exactas, la ventana de cálculo y un desglose de cómo se formó el número de cumplimiento. Incluye un gráfico de disponibilidad a lo largo del tiempo y una lista de incidentes que contaron para el SLA.
Línea temporal del incidente (para auditorías). Una vista de un solo incidente debe mostrar una línea temporal de eventos (detectado, reconocido, mitigado, resuelto) y qué timestamps se usaron para las métricas de “respuesta” y “resolución”.
Haz los filtros consistentes en todas las pantallas: rango de fechas, cliente, servicio, nivel y severidad. Usa las mismas unidades en todas partes (minutos vs segundos; porcentajes con los mismos decimales). Cuando los usuarios cambien el rango, actualiza todas las métricas de la página para evitar desajustes.
Cada métrica resumen debe tener una ruta “¿Por qué?”:
Usa tooltips con moderación para definir términos como “Downtime excluido” u “Horario laboral”, y muestra el texto exacto de la regla en la página de servicio para evitar conjeturas.
Prefiere lenguaje claro sobre abreviaturas (“Tiempo de respuesta” en vez de “MTTA” a menos que la audiencia lo espere). Para el estado, combina color con etiquetas textuales (“En riesgo: 92% del presupuesto de errores usado”) para evitar ambigüedad. Si la app soporta logs de auditoría, añade una caja pequeña “Último cambio” en las reglas SLA y en exclusiones enlazando a /settings/audit-log para que los usuarios verifiquen cuándo cambiaron las definiciones.
Las alertas son donde tu app de seguimiento SLA deja de ser un informe pasivo y empieza a ayudar a equipos a evitar penalizaciones. Las mejores alertas son oportunas, específicas y accionables—es decir, dicen a alguien qué hacer después, no solo que algo está “mal”.
Empieza con tres tipos de disparadores:
Haz los disparadores configurables por cliente/servicio/SLA, ya que distintos contratos toleran umbrales distintos.
Envía alertas donde la gente realmente responde:
Cada alerta debe incluir enlaces profundos como /alerts, /customers/{id}, /services/{id}, y la página de detalle del incidente o evento para que los respondedores puedan verificar números rápidamente.
Aplica deduplicación agrupando alertas con la misma clave (cliente + servicio + SLA + periodo) y suprimiendo repeticiones durante una ventana de cooldown.
Añade horarios de silencio por zona horaria del equipo para que alertas no críticas de “cercano a incumplimiento” esperen a horario laboral, mientras que “incumplimiento ocurrido” puede saltarse el silencio si la severidad es alta.
Finalmente, soporta reglas de escalado (p. ej., notificar al on-call tras 10 minutos, escalar a un manager tras 30) para evitar que alertas se queden atascadas en un buzón.
Los datos de SLA son sensibles porque exponen rendimiento interno y entitlements específicos de clientes. Trata el control de acceso como parte de la “aritmética” SLA: el mismo incidente puede producir distintos resultados según qué SLA se aplique.
Mantén roles simples y luego afina permisos.
Un default práctico es RBAC + scoping por tenant:
Sé explícito con datos por cliente:
Empieza con email/contraseña y exige MFA para roles internos. Planea SSO (SAML/OIDC) separando identidad (quién es) de autorización (qué puede acceder). Para integraciones, emite API keys ligadas a una cuenta de servicio con ámbitos estrechos y soporte de rotación.
Añade entradas inmutables para:
Almacena quién, qué cambió (antes/después), cuándo, dónde (IP/user agent) y un ID de correlación. Haz los logs buscables y exportables (p. ej., /settings/audit-log).
Una app de seguimiento SLA raramente es una isla. Querrás una API que permita a herramientas de monitorización, sistemas de ticketing y flujos internos crear incidentes, enviar eventos y extraer informes sin trabajo manual.
Usa un path versionado (por ejemplo, /api/v1/...) para poder evolucionar payloads sin romper integraciones existentes.
Endpoints esenciales:
POST /api/v1/events para ingerir cambios de estado (up/down, muestras de latencia, ventanas de mantenimiento). GET /api/v1/events para auditorías y depuración.POST /api/v1/incidents, PATCH /api/v1/incidents/{id} (acknowledge, resolve, assign), GET /api/v1/incidents.GET /api/v1/slas, POST /api/v1/slas, PUT /api/v1/slas/{id} para gestionar contratos y umbrales.GET /api/v1/reports/sla?service_id=...&from=...&to=... para resúmenes de cumplimiento.POST /api/v1/alerts/subscriptions para gestionar webhooks/targets de email; GET /api/v1/alerts para historial de alertas.Elige una convención y úsala en todos lados. Por ejemplo: limit, paginación por cursor, más filtros estándar como service_id, sla_id, status, from, to. Mantén el orden predecible (p. ej., sort=-created_at).
Devuelve errores estructurados con campos estables:
{ "error": { "code": "VALIDATION_ERROR", "message": "service_id is required", "fields": { "service_id": "missing" } } }
Usa códigos HTTP claros (400 validación, 401/403 auth, 404 not found, 409 conflict, 429 rate limit). Para ingesta de eventos, considera idempotencia (Idempotency-Key) para que los reintentos no dupliquen incidentes.
Aplica rate limits razonables por token (y más estrictos para endpoints de ingesta), sanitiza inputs y valida timestamps/zona horaria. Prefiere tokens API con ámbitos (solo lectura vs escritura de incidentes), y registra quién llamó a qué endpoint para trazabilidad (detalles en tu sección de auditoría en /blog/audit-logs).
Los números SLA solo sirven si la gente confía en ellos. Las pruebas para una app de seguimiento SLA deben centrarse menos en “¿carga la página?” y más en “¿la aritmética temporal se comporta exactamente como dice el contrato?” Trata tus reglas de cálculo como una característica del producto con su propio suite de tests.
Empieza testeando unitariamente tu motor con entradas deterministas: una línea temporal de eventos (incidente abierto, reconocido, mitigado, resuelto) y un conjunto de reglas SLA claramente definido.
Usa timestamps fijos y “freeze time” para que las pruebas no dependan del reloj. Cubre casos límite que suelen romper los informes SLA:
Añade un pequeño conjunto de pruebas E2E que ejecuten el flujo completo: ingerir eventos → calcular cumplimiento → generar informe → renderizar UI. Estas detectan desajustes entre “lo que el motor calculó” y “lo que muestra el dashboard.” Mantén los escenarios pocos pero de alto valor y aserta en números finales (%, incumplimiento sí/no, tiempo hasta ack).
Crea fixtures para horario laboral, festivos y zonas horarias. Quieres casos repetibles como “incidente ocurre viernes 17:55 hora local” y “un festivo desplaza el conteo del tiempo de respuesta.”
Las pruebas no terminan al desplegar. Añade monitorización para fallos de jobs, tamaño de cola/backlog, duración de recalculación y tasas de error. Si la ingesta se atrasa o un job nocturno falla, tu informe SLA puede estar mal aunque el código sea correcto.
Lanzar una app de seguimiento SLA tiene menos que ver con infraestructura sofisticada y más con operaciones predecibles: tus cálculos deben correr a tiempo, los datos deben estar seguros y los informes reproducibles.
Empieza con servicios gestionados para poder centrarte en la corrección:
Mantén entornos mínimos: dev → staging → prod, cada uno con su propia BD y secretos.
El seguimiento SLA no es puramente request/response; depende de trabajo programado.
Ejecuta jobs vía un proceso worker + cola o un scheduler gestionado invocando endpoints internos. Haz los jobs idempotentes (seguros de reintentar) y registra cada ejecución para auditoría.
Define retención por tipo de dato: conserva resultados derivados más tiempo que las corrientes de eventos crudos. Para exportes, ofrece CSV primero (rápido, transparente) y luego plantillas PDF. Sé claro: las exportaciones son "mejor esfuerzo" en formato, mientras que la base de datos es la fuente de la verdad.
Si quieres validar modelo de datos, flujo de ingesta y UI de informes rápidamente, una plataforma de vibe-coding como Koder.ai puede ayudarte a llegar a un prototipo end-to-end sin comprometerte con un ciclo completo de ingeniería. Porque Koder.ai genera aplicaciones completas vía chat (UI web + backend), es práctico para montar:
Una vez que los requisitos y cálculos estén probados (la parte dura), puedes iterar, exportar el código fuente y pasar a un flujo de build-and-operate más tradicional—manteniendo funcionalidades como snapshots y rollback durante la iteración rápida.
Un rastreador de SLA responde a una pregunta con evidencia: ¿cumplimos los compromisos contractuales para un cliente y periodo concreto?
En la práctica, significa ingerir señales crudas (monitorización, tickets, actualizaciones manuales), aplicar las reglas del cliente (horario laboral, exclusiones) y producir un resultado auditable: aprobado/fallado más detalles que lo respaldan.
Usa:
Modelarlos por separado te permite mejorar la fiabilidad (SLO) sin cambiar accidentalmente los informes contractuales (SLA).
Un MVP sólido suele rastrear 1–3 métricas de extremo a extremo:
Estas métricas se mapean claramente a fuentes de datos reales y te obligan a implementar las partes complejas (periodos, calendarios, exclusiones) desde el inicio.
Los fallos de requisitos suelen venir de reglas no declaradas. Recopila y redacta:
Si una regla no puede expresarse claramente, no la infieras en código: fíjala y aclárala.
Empieza con entidades aburridas y explícitas:
Busca trazabilidad: cada número reportado debe enlazar a IDs de eventos concretos y a una versión de política específica.
Almacena el tiempo correcta y consistentemente:
occurred_at en UTC con semántica de zona horariareceived_at (cuando lo ingirió tu sistema)Además, haz explícitos los periodos (timestamps de inicio/fin) para poder reproducir informes más tarde—even en cambios de DST.
Normaliza todo en una sola forma interna de evento con un ID estable:
event_id (único, estable ante reintentos)source, event_type, occurred_at, service_idincident_id y attributesAplica idempotencia con una restricción única en event_id. Para mappings faltantes o llegadas fuera de orden, cuarentena/etiqueta—no "arregles" los datos en silencio.
Calcula duraciones sumando intervalos en una línea temporal, no restando dos timestamps a ciegas.
Define el “tiempo cobrable” eliminando intervalos que no cuentan, como:
Persiste los intervalos derivados y los códigos de motivo para poder explicar exactamente qué se contó.
Rastrea dos denominadores explícitos:
Luego calcula:
availability_percent = 100 * (eligible_minutes - downtime_minutes) / eligible_minutes
Decide qué hacer si minutos elegibles es cero (por ejemplo, mostrar N/A) y documenta esa regla.
Haz que la UI responda “¿estamos cumpliendo el SLA y por qué?” de un vistazo:
Para alertas, prioriza disparadores accionables: acercándose al incumplimiento, incumplimiento ocurrido y violaciones repetidas—cada una enlazando a páginas relevantes como /customers/{id} o /services/{id}.