Dentro de seis meses, alguien en Reservalia preguntará: "¿ha servido de algo todo esto?". Si el equipo responde "sí, ahora vamos mucho más rápido", la conversación se convertirá en una discusión de sensaciones. Si responde "el tiempo desde el commit hasta producción ha bajado de 9 días a 40 minutos y el porcentaje de despliegues que provocan incidente ha pasado del 15 % al 3 %", la conversación se acaba. Esta lección va de eso: de convertir la calidad de la entrega de software en números que se pueden verificar. Las métricas DORA son el estándar del sector para hacerlo, y su mayor virtud es que son solo cuatro, se calculan con datos que el propio pipeline genera, y no se pueden manipular a la vez —mejorar velocidad estropeando estabilidad se ve inmediatamente. Al terminar sabrás qué mide cada una, de qué evento del pipeline sale el dato, cómo instrumentarlas sin comprar herramienta alguna, y por qué convertirlas en objetivos individuales es la forma más rápida de destruir su utilidad.

Contenido

  1. Qué son las métricas DORA y por qué son cuatro
  2. Métrica 1: frecuencia de despliegue
  3. Métrica 2: lead time for changes
  4. Métrica 3: change failure rate
  5. Métrica 4: time to restore service
  6. La quinta métrica: fiabilidad
  7. Rangos orientativos de rendimiento
  8. Cómo instrumentarlas de forma sencilla
  9. Calcular el lead time con bash y json
  10. Consultar las métricas con SQL
  11. El cuadro de mando inicial de Reservalia
  12. La ley de Goodhart: cuando la métrica se convierte en objetivo
  13. Errores comunes y consejos
  14. Ejercicios
  15. Conclusión

  1. Qué son las métricas DORA y por qué son cuatro

DORA son las siglas de DevOps Research and Assessment, el programa de investigación que durante años ha encuestado a decenas de miles de profesionales para identificar qué prácticas distinguen a los equipos que entregan software mejor. Su aportación más útil y más citada es un conjunto de cuatro métricas que resumen el rendimiento de la entrega.

Lo interesante no es la lista, es su estructura. Las cuatro se agrupan en dos parejas que tiran en direcciones opuestas:

graph TB
    subgraph V["⚡ VELOCIDAD (¿con qué rapidez entregamos?)"]
        V1["1· Frecuencia de despliegue<br/>¿cada cuánto llega algo a producción?"]
        V2["2· Lead time for changes<br/>¿cuánto tarda un cambio en llegar?"]
    end
    subgraph E["🛡️ ESTABILIDAD (¿con qué calidad entregamos?)"]
        E1["3· Change failure rate<br/>¿qué porcentaje de cambios rompe algo?"]
        E2["4· Time to restore service<br/>¿cuánto tardamos en arreglarlo?"]
    end
    V -.->|"se equilibran"| E
    style V fill:#cfe8ff
    style E fill:#d9f2d9

Esta tensión es lo que hace que el conjunto sea difícil de falsear:

  • Si solo midieras velocidad, la forma trivial de "mejorar" sería desplegar sin probar nada. La estabilidad se hundiría y se vería al instante.
  • Si solo midieras estabilidad, la forma trivial de "mejorar" sería no desplegar nunca. La velocidad se hundiría y también se vería.

El hallazgo central del programa es contraintuitivo y merece leerse dos veces: velocidad y estabilidad no se oponen; van juntas. Los equipos que despliegan más a menudo también fallan menos y se recuperan antes. La razón la vimos en la lección 01-02: desplegar a menudo obliga a lotes pequeños, y los lotes pequeños son más fáciles de verificar, de diagnosticar y de revertir. El miedo a desplegar produce lotes grandes, y los lotes grandes producen incidentes. Es un círculo, y se puede recorrer en los dos sentidos.

  1. Métrica 1: frecuencia de despliegue

Qué mide. Con qué frecuencia una organización lleva código a producción con éxito.

2.1. Cómo se calcula

frecuencia de despliegue = nº de despliegues exitosos a producción
                           ──────────────────────────────────────
                                    periodo de tiempo

Tres precisiones que cambian mucho el resultado:

  • Solo producción. Los despliegues a dev y staging no cuentan. Lo que mide la métrica es cuánto valor llega a los usuarios.
  • Solo los exitosos. Un despliegue que se revierte inmediatamente no cuenta como entrega; contará en la métrica 3.
  • Por servicio desplegable, no por empresa. Si Reservalia despliega api y web por separado, se mide cada una. Sumar servicios de toda la organización produce un número grande y sin significado.

2.2. De qué evento del pipeline sale el dato

Del final del job de despliegue a producción, cuando termina correctamente. Es el dato más fácil de capturar de los cuatro: basta con registrar una fila cada vez que un despliegue a prod acaba en verde.

2.3. Qué te dice realmente

La frecuencia de despliegue es un indicador indirecto del tamaño del lote, y por eso importa tanto. Un equipo que despliega una vez cada dos semanas está acumulando dos semanas de cambios en cada entrega, con todo lo que eso implica (sección 4 de la lección 01-02).

También revela cuánta fricción tiene el proceso. Nadie despliega diez veces al día si cada despliegue cuesta tres horas de trabajo manual. La frecuencia baja casi nunca es una decisión: es un síntoma.

  1. Métrica 2: lead time for changes

Qué mide. El tiempo que transcurre desde que un cambio se confirma en el repositorio hasta que está funcionando en producción.

Es probablemente la métrica más valiosa de las cuatro, porque atraviesa todo el proceso.

3.1. Cómo se calcula

lead time = fecha del despliegue a producción − fecha del commit

Se calcula para cada commit y se reporta como mediana (o percentil 50) del periodo. Aquí hay una decisión metodológica importante:

Usa la mediana, no la media. Un solo cambio que se quedó tres meses en una rama olvidada destroza la media y no representa nada. La mediana te dice cuánto tarda el cambio típico, que es lo que quieres saber. El percentil 90 también es útil: te dice cómo de malo es el peor caso habitual.

3.2. De qué evento del pipeline sale el dato

De dos eventos, y por eso es la métrica que más gente calcula mal:

Extremo Dónde está el dato Cómo se obtiene
Inicio Metadatos del commit en Git git show -s --format=%cI <sha>
Fin Registro del despliegue a producción Marca de tiempo del job de despliegue

El error habitual es medir desde que arranca el pipeline en lugar de desde el commit. Eso mide el rendimiento del pipeline (útil, pero es otra cosa) y oculta precisamente lo que suele ser el problema: el tiempo de espera. En Reservalia, el pipeline tardaría 8 minutos, pero el cambio espera hasta 9 días al viernes. Si mides desde el arranque del pipeline, tu lead time es de 8 minutos y estarías engañándote.

3.3. Un matiz sobre commits y despliegues

Un despliegue suele incluir varios commits. El lead time se calcula por commit: cada uno de los commits incluidos en el despliegue recibe la misma fecha de fin, pero tiene su propia fecha de inicio.

gantt
    title Lead time de tres commits desplegados juntos
    dateFormat YYYY-MM-DD HH:mm
    axisFormat %d/%m %H:%M
    section Commits
    commit a3f9c21 (lead time 26 h) :a1, 2026-03-13 09:00, 26h
    commit b7e2d10 (lead time 5 h)  :a2, 2026-03-14 06:00, 5h
    commit c1d4a55 (lead time 1 h)  :a3, 2026-03-14 10:00, 1h

Los tres se despliegan a las 11:00 del 14 de marzo, pero sus lead times son muy distintos. La mediana de esos tres sería 5 horas.

3.4. Qué te dice realmente

El lead time descompone el proceso. Cuando es alto, el diagnóstico consiste en preguntarse dónde se va el tiempo:

Tramo Qué lo alarga Dónde se ataca en el curso
Commit → pipeline arrancado Nada, si el trigger es automático 02-07
Pipeline de verificación Suite lenta, sin paralelismo, sin caché 04-04
Pipeline → revisión aprobada Revisiones lentas, PR demasiado grandes 02-07
Merge → despliegue disponible Falta de automatización del despliegue 03-02
Despliegue disponible → producción Ventanas de despliegue, aprobaciones lentas, miedo 03-01, 03-04

En la inmensa mayoría de equipos, el tramo dominante es el último. Y ese no se arregla comprando runners más rápidos.

  1. Métrica 3: change failure rate

Qué mide. El porcentaje de despliegues a producción que provocan una degradación del servicio y requieren una intervención correctiva inmediata (rollback, corrección urgente, parche).

4.1. Cómo se calcula

change failure rate = despliegues que causaron un fallo × 100
                      ───────────────────────────────────────
                           total de despliegues a producción

4.2. La parte difícil: definir "fallo"

Esta es la métrica más subjetiva de las cuatro, y su valor depende por completo de que el equipo acuerde una definición antes de empezar a medir y no la cambie después. Una definición operativa razonable para Reservalia:

Un despliegue cuenta como fallido si, como consecuencia directa, ocurre alguna de estas cosas:

  • Hubo que revertirlo.
  • Hubo que desplegar una corrección urgente fuera del flujo normal en las horas siguientes.
  • Se degradó el servicio de forma perceptible para los usuarios (errores, lentitud grave, funcionalidad rota).
  • Hubo que activar un feature flag de emergencia para desactivar lo desplegado.

No cuenta como fallido:

  • Un fallo detectado en staging y que nunca llegó a producción. Eso es el sistema funcionando.
  • Un bug que llevaba tres meses en producción y se descubre ahora: no lo causó este despliegue.
  • Una caída de un proveedor externo no relacionada con el cambio.

Escribid esa definición en el repositorio. Sin ella, la métrica se vuelve inservible en cuanto haya un caso ambiguo y alguien decida sobre la marcha.

4.3. De qué evento del pipeline sale el dato

Este es el único dato de los cuatro que no sale automáticamente del pipeline: requiere una decisión humana. Las fuentes prácticas son:

  • Un rollback automático disparado por las métricas: se registra solo (03-05).
  • Un despliegue marcado a mano como fallido por quien gestiona el incidente.
  • La vinculación entre el incidente y el despliegue que lo causó, hecha en el post mortem.

Lo más práctico es un comando o un botón que Nuria pueda usar durante el incidente:

# Marcar el último despliegue de producción como fallido.
# Lo ejecuta quien gestiona el incidente, mientras lo gestiona.
./scripts/marcar-despliegue-fallido.sh \
  --despliegue dep_2026_0314_1042 \
  --motivo "error 500 al crear citas tras el cambio de esquema" \
  --detectado-en "2026-03-14T11:05:00+01:00"

Si registrar el fallo cuesta más de treinta segundos, nadie lo hará durante una crisis y tus datos serán falsos.

4.4. Qué te dice realmente

Un change failure rate alto apunta a huecos concretos en la verificación: pruebas insuficientes, entorno de staging que no se parece a producción, o lotes demasiado grandes. Un valor sospechosamente bajo (0 % sostenido) suele significar que no se está registrando, no que no falla nada.

  1. Métrica 4: time to restore service

Qué mide. Cuánto tarda la organización en restablecer el servicio cuando se produce una degradación o caída en producción.

5.1. Cómo se calcula

time to restore = fecha de restablecimiento del servicio − fecha de inicio del incidente

Se reporta como mediana de los incidentes del periodo.

Ojo con los dos extremos:

  • Inicio del incidente: cuando el problema empezó a afectar a los usuarios, no cuando alguien se dio cuenta. Si el servicio estuvo roto 25 minutos antes de que llamara un cliente, esos 25 minutos cuentan. Medir desde la detección premia tener mala monitorización, que es exactamente el incentivo contrario al deseable.
  • Restablecimiento: cuando los usuarios vuelven a estar bien, no cuando se entiende la causa raíz. Un rollback restablece el servicio aunque nadie sepa todavía qué pasó. El análisis viene después.

5.2. De qué evento sale el dato

De la gestión del incidente: hora de inicio y hora de resolución. Idealmente, la hora de inicio la aporta la monitorización automática (materia de 03-06) y no la memoria de nadie.

5.3. Qué te dice realmente

Es, junto con la frecuencia, la métrica que más rápido mejora al automatizar. En Reservalia hoy, restablecer significa recompilar y volver a subir por SFTP: alrededor de una hora. Con artefactos inmutables en ECR, restablecer es redesplegar la imagen anterior: minutos.

Esta métrica captura una idea profunda de DevOps: no se puede evitar que los fallos ocurran; sí se puede hacer que duren poco. Un equipo que falla el 5 % de las veces pero se recupera en 4 minutos ofrece un servicio mucho mejor que uno que falla el 2 % y tarda 6 horas.

  1. La quinta métrica: fiabilidad

A las cuatro clásicas se añadió después una quinta: la fiabilidad (reliability). Es distinta de las anteriores en su naturaleza y por eso conviene explicarla aparte.

Qué mide. Hasta qué punto el servicio cumple las expectativas de sus usuarios en cuanto a disponibilidad, latencia y corrección.

Las cuatro primeras miden el proceso de entrega; la quinta mide el resultado operativo. Es la que impide un fallo de razonamiento tentador: un equipo puede tener las cuatro métricas en verde y, aun así, ofrecer un servicio malo —lento, con funcionalidad correcta pero inservible, o caído fuera de los momentos que cuentan como "incidente".

No tiene una fórmula única. Se instrumenta mediante objetivos de nivel de servicio (SLO) definidos por el propio equipo. Para Reservalia, tres razonables:

Objetivo de nivel de servicio Umbral Por qué este
Disponibilidad de la API ≥ 99,9 % mensual en horario comercial Una caída a las 4 de la mañana molesta menos que una a las 11:00 de un sábado
Latencia de creación de cita percentil 95 < 800 ms Si reservar es lento, el cliente final abandona
Éxito del envío de recordatorios ≥ 99,5 % enviados en la ventana correcta Un recordatorio que no llega es una cita perdida para el negocio

Fíjate en el matiz del primero: "en horario comercial". Una plataforma de reservas para peluquerías y clínicas se juega su valor entre las 9:00 y las 20:00. Un objetivo de disponibilidad plano ignora eso. Definir bien un SLO consiste precisamente en capturar lo que de verdad le importa al usuario.

Las herramientas para medir esto —observabilidad, paneles y alertas— se ven en la lección 03-06.

  1. Rangos orientativos de rendimiento

El programa DORA clasifica a los equipos en cuatro niveles. Estos son los rangos orientativos:

Métrica Bajo Medio Alto Elite
Frecuencia de despliegue Menos de una vez al mes Entre una vez al mes y una vez a la semana Entre una vez a la semana y una vez al día Bajo demanda, varias veces al día
Lead time for changes Más de un mes Entre una semana y un mes Entre un día y una semana Menos de un día
Change failure rate Alto (en torno al 40 % o más) Moderado (en torno al 20-30 %) Moderado-bajo (en torno al 15 %) Bajo (en torno al 5 % o menos)
Time to restore service Más de una semana Entre un día y una semana Menos de un día Menos de una hora

7.1. Advertencia imprescindible sobre esta tabla

Estos rangos son referencias para orientarte, no objetivos que perseguir a ciegas. Cuatro razones concretas:

  1. Los umbrales se mueven. Cada edición del informe reajusta las fronteras. Lo que hace unos años era "elite" hoy es "alto". Perseguir una etiqueta es perseguir un objetivo móvil.
  2. El contexto lo cambia todo. Un equipo que desarrolla software médico certificado nunca desplegará varias veces al día, y eso no lo convierte en un mal equipo: lo convierte en un equipo que cumple la normativa de su sector. Comparar un SaaS con un sistema de aviónica no tiene sentido.
  3. Comparar equipos con estas etiquetas es tóxico. Sirven para compararte contigo mismo a lo largo del tiempo. En el momento en que se usan para rankings internos entre equipos, empieza la manipulación de datos (sección 12).
  4. "Elite" no es el objetivo correcto para todos. Para Reservalia, pasar de desplegar una vez a la semana a hacerlo una vez al día sería una transformación enorme. Fijarse "varias veces al día" como meta inicial solo produce frustración.

La pregunta correcta no es "¿en qué nivel estamos?" sino "¿vamos mejor que hace tres meses?".

  1. Cómo instrumentarlas de forma sencilla

No hace falta comprar ninguna herramienta. Basta con registrar un evento por despliegue y otro por incidente. Con eso se calculan tres de las cuatro métricas directamente, y la cuarta con una marca manual.

8.1. El modelo de datos mínimo

-- Todo lo necesario para las métricas DORA cabe en dos tablas.

CREATE TABLE despliegues (
  id                TEXT PRIMARY KEY,        -- dep_2026_0314_1042
  servicio          TEXT NOT NULL,           -- 'api' | 'web'
  entorno           TEXT NOT NULL,           -- 'dev' | 'staging' | 'prod'
  commit_sha        TEXT NOT NULL,
  commit_fecha      TIMESTAMPTZ NOT NULL,    -- ← inicio del lead time
  desplegado_en     TIMESTAMPTZ NOT NULL,    -- ← fin del lead time
  resultado         TEXT NOT NULL,           -- 'exito' | 'fallo_pipeline'
  fallido           BOOLEAN NOT NULL DEFAULT false,  -- ← change failure rate
  motivo_fallo      TEXT,
  commits_incluidos INTEGER NOT NULL DEFAULT 1,
  pipeline_url      TEXT
);

CREATE TABLE incidentes (
  id             TEXT PRIMARY KEY,
  servicio       TEXT NOT NULL,
  inicio         TIMESTAMPTZ NOT NULL,   -- cuando empezó a AFECTAR a usuarios
  restablecido   TIMESTAMPTZ,            -- NULL mientras siga abierto
  despliegue_id  TEXT REFERENCES despliegues(id),  -- si lo causó un despliegue
  severidad      TEXT NOT NULL           -- 'critica' | 'alta' | 'media'
);

Dos decisiones de diseño que conviene entender:

  • commit_fecha se guarda en la tabla, en lugar de consultarla a Git cada vez. Los repositorios se reescriben, las ramas se borran y las consultas a Git son lentas. Guardar el dato en el momento del despliegue lo congela.
  • despliegue_id en incidentes es opcional. No todos los incidentes los causa un despliegue (puede caerse un proveedor). Esa relación es justamente la que permite calcular el change failure rate sin contaminarlo con incidentes ajenos.

8.2. Dónde se rellena cada campo

flowchart LR
    A["Job de despliegue<br/>a prod termina OK"] -->|"INSERT"| B[("tabla despliegues")]
    C["Monitorización detecta<br/>degradación"] -->|"INSERT"| D[("tabla incidentes")]
    E["Nuria marca el<br/>despliegue culpable"] -->|"UPDATE fallido=true"| B
    F["Servicio restablecido"] -->|"UPDATE restablecido"| D
    B --> G["📊 Cuadro de mando<br/>4 métricas"]
    D --> G

  1. Calcular el lead time con bash y json

Veamos el mecanismo concreto, paso a paso. Primero, obtener los dos extremos.

9.1. Los datos de partida

#!/usr/bin/env bash
# registrar-despliegue.sh
# Se ejecuta como ÚLTIMO paso del job de despliegue a producción.
set -euo pipefail   # -e: aborta si algo falla | -u: error si hay variable no definida
                    # -o pipefail: un fallo en una tubería no pasa desapercibido

SHA="$(git rev-parse HEAD)"

# Fecha del COMMIT, en formato ISO 8601 con zona horaria.
# %cI = "committer date, strict ISO 8601". Es el inicio del lead time.
COMMIT_FECHA="$(git show -s --format=%cI "$SHA")"

# Fecha del DESPLIEGUE: ahora mismo, en UTC. Es el fin del lead time.
DESPLIEGUE_FECHA="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

echo "Commit    : $SHA"
echo "Commiteado: $COMMIT_FECHA"
echo "Desplegado: $DESPLIEGUE_FECHA"

Por qué ISO 8601 con zona horaria. Un 2026-03-14 10:22 sin zona es ambiguo: ¿hora de Madrid, UTC, del runner? Con cambios de hora de por medio, esa ambigüedad produce lead times negativos o de una hora de más. Trabaja siempre en UTC internamente y convierte solo al mostrar.

9.2. Calcular la diferencia

# Convertimos ambas fechas a segundos desde la época Unix y restamos.
# Esto elimina de un plumazo los problemas de zonas horarias y meses.
COMMIT_EPOCH="$(date -d "$COMMIT_FECHA" +%s)"
DESPLIEGUE_EPOCH="$(date -d "$DESPLIEGUE_FECHA" +%s)"

LEAD_TIME_SEG=$(( DESPLIEGUE_EPOCH - COMMIT_EPOCH ))
LEAD_TIME_MIN=$(( LEAD_TIME_SEG / 60 ))
LEAD_TIME_H=$(( LEAD_TIME_SEG / 3600 ))

echo "Lead time: ${LEAD_TIME_SEG}s = ${LEAD_TIME_MIN} min = ${LEAD_TIME_H} h"

Un ejemplo con números reales:

# Commit    : 2026-03-13T09:00:00+01:00  → epoch 1773388800
# Desplegado: 2026-03-14T11:00:00Z       → epoch 1773486000
# Diferencia: 97200 segundos = 1620 minutos = 27 horas

9.3. Construir el registro en JSON

# Generamos el evento como JSON. jq garantiza un escapado correcto:
# construir JSON concatenando cadenas con comillas es una fuente clásica
# de ficheros corruptos en cuanto un mensaje de commit lleva comillas.
jq -n \
  --arg id          "dep_$(date -u +%Y%m%d_%H%M%S)" \
  --arg servicio    "api" \
  --arg entorno     "prod" \
  --arg sha         "$SHA" \
  --arg commit_f    "$COMMIT_FECHA" \
  --arg desp_f      "$DESPLIEGUE_FECHA" \
  --argjson lead    "$LEAD_TIME_SEG" \
  --argjson commits "$(git rev-list --count "${SHA_ANTERIOR}..${SHA}")" \
  '{
     id:                $id,
     servicio:          $servicio,
     entorno:           $entorno,
     commit_sha:        $sha,
     commit_fecha:      $commit_f,
     desplegado_en:     $desp_f,
     lead_time_segundos:$lead,
     commits_incluidos: $commits,
     resultado:         "exito",
     fallido:           false
   }' > despliegue.json

cat despliegue.json

Resultado:

{
  "id": "dep_20260314_110000",
  "servicio": "api",
  "entorno": "prod",
  "commit_sha": "a3f9c21e4b7d8f012345678901234567890abcde",
  "commit_fecha": "2026-03-13T09:00:00+01:00",
  "desplegado_en": "2026-03-14T11:00:00Z",
  "lead_time_segundos": 97200,
  "commits_incluidos": 3,
  "resultado": "exito",
  "fallido": false
}

9.4. Calcular el lead time de cada commit del despliegue

Recuerda la sección 3.3: un despliegue incluye varios commits y cada uno tiene su propio lead time. Este script los calcula todos:

#!/usr/bin/env bash
# lead-time-por-commit.sh <sha_desplegado_anterior> <sha_actual>
set -euo pipefail

SHA_ANTERIOR="$1"    # lo que había en producción
SHA_ACTUAL="$2"      # lo que acabamos de desplegar
AHORA_EPOCH="$(date -u +%s)"

# git rev-list lista todos los commits entre ambos puntos.
# --format=%H|%cI da: hash|fecha ISO. --no-commit-header evita líneas extra.
git rev-list --format="%H|%cI" --no-commit-header "${SHA_ANTERIOR}..${SHA_ACTUAL}" \
| while IFS='|' read -r sha fecha; do
    commit_epoch="$(date -d "$fecha" +%s)"
    lead_min=$(( (AHORA_EPOCH - commit_epoch) / 60 ))
    printf '%s  %s  lead_time=%d min\n' "${sha:0:7}" "$fecha" "$lead_min"
  done

Salida de ejemplo:

c1d4a55  2026-03-14T10:00:00+01:00  lead_time=60 min
b7e2d10  2026-03-14T06:00:00+01:00  lead_time=300 min
a3f9c21  2026-03-13T09:00:00+01:00  lead_time=1620 min

Tres commits, tres lead times muy distintos. La mediana es 300 minutos (5 horas). La media sería 660 minutos, muy distorsionada por el commit antiguo: exactamente el motivo por el que se usa la mediana.

  1. Consultar las métricas con SQL

Con la tabla despliegues poblada, las métricas son consultas de pocas líneas.

10.1. Frecuencia de despliegue

-- Despliegues exitosos a producción, por semana, del servicio 'api'.
SELECT
  date_trunc('week', desplegado_en) AS semana,
  COUNT(*)                          AS despliegues
FROM despliegues
WHERE entorno   = 'prod'
  AND servicio  = 'api'
  AND resultado = 'exito'
  AND desplegado_en >= now() - interval '12 weeks'
GROUP BY semana
ORDER BY semana;
   semana   | despliegues
------------+-------------
 2026-01-05 |           1
 2026-01-12 |           1
 2026-01-19 |           0
 2026-01-26 |           2      ← una corrección urgente además del viernes

El patrón de "1 por semana" delata inmediatamente el ritual del viernes de Reservalia.

10.2. Lead time (mediana y percentil 90)

-- Mediana y P90 del lead time, en horas, por mes.
SELECT
  date_trunc('month', desplegado_en) AS mes,
  ROUND(
    PERCENTILE_CONT(0.5) WITHIN GROUP (
      ORDER BY EXTRACT(EPOCH FROM (desplegado_en - commit_fecha))
    ) / 3600.0, 1
  ) AS lead_time_mediana_h,
  ROUND(
    PERCENTILE_CONT(0.9) WITHIN GROUP (
      ORDER BY EXTRACT(EPOCH FROM (desplegado_en - commit_fecha))
    ) / 3600.0, 1
  ) AS lead_time_p90_h,
  COUNT(*) AS n
FROM despliegues
WHERE entorno = 'prod' AND resultado = 'exito'
GROUP BY mes
ORDER BY mes;

Explicación de la consulta, para quien no haya visto PERCENTILE_CONT:

  • desplegado_en - commit_fecha da un intervalo; EXTRACT(EPOCH FROM ...) lo convierte a segundos.
  • PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ...) calcula la mediana de esos segundos.
  • Se divide entre 3600 para pasarlo a horas.
  • Se incluye COUNT(*) siempre: una mediana calculada sobre 2 despliegues no significa nada, y sin el recuento no lo sabrías.

10.3. Change failure rate

-- Porcentaje de despliegues a producción que provocaron un fallo, por mes.
SELECT
  date_trunc('month', desplegado_en)                       AS mes,
  COUNT(*)                                                  AS total,
  COUNT(*) FILTER (WHERE fallido)                           AS fallidos,
  ROUND(100.0 * COUNT(*) FILTER (WHERE fallido) / COUNT(*), 1) AS pct_fallo
FROM despliegues
WHERE entorno = 'prod' AND resultado = 'exito'
GROUP BY mes
ORDER BY mes;
    mes     | total | fallidos | pct_fallo
------------+-------+----------+-----------
 2026-01-01 |     5 |        1 |      20.0
 2026-02-01 |     4 |        0 |       0.0
 2026-03-01 |     4 |        1 |      25.0

Nótese el WHERE resultado = 'exito': el denominador son los despliegues que llegaron a producción. Un pipeline que falla antes de desplegar no es un cambio fallido: es el sistema protegiéndote.

10.4. Time to restore service

-- Mediana del tiempo de restablecimiento, en minutos, por trimestre.
SELECT
  date_trunc('quarter', inicio) AS trimestre,
  COUNT(*)                      AS incidentes,
  ROUND(
    PERCENTILE_CONT(0.5) WITHIN GROUP (
      ORDER BY EXTRACT(EPOCH FROM (restablecido - inicio))
    ) / 60.0, 1
  ) AS restauracion_mediana_min
FROM incidentes
WHERE restablecido IS NOT NULL      -- solo incidentes ya cerrados
  AND severidad IN ('critica', 'alta')
GROUP BY trimestre
ORDER BY trimestre;

10.5. Las cuatro de un vistazo

-- Cuadro de mando: las cuatro métricas del último trimestre.
WITH ventana AS (
  SELECT * FROM despliegues
  WHERE entorno = 'prod' AND resultado = 'exito'
    AND desplegado_en >= now() - interval '90 days'
)
SELECT
  'Frecuencia de despliegue' AS metrica,
  ROUND(COUNT(*) / 12.85, 2) || ' por semana' AS valor
FROM ventana
UNION ALL
SELECT
  'Lead time (mediana)',
  ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (
    ORDER BY EXTRACT(EPOCH FROM (desplegado_en - commit_fecha))
  ) / 3600.0, 1) || ' h'
FROM ventana
UNION ALL
SELECT
  'Change failure rate',
  ROUND(100.0 * COUNT(*) FILTER (WHERE fallido) / NULLIF(COUNT(*), 0), 1) || ' %'
FROM ventana
UNION ALL
SELECT
  'Time to restore (mediana)',
  ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (
    ORDER BY EXTRACT(EPOCH FROM (restablecido - inicio))
  ) / 60.0, 1) || ' min'
FROM incidentes
WHERE restablecido IS NOT NULL AND inicio >= now() - interval '90 days';

El NULLIF(COUNT(*), 0) evita una división por cero cuando no hay despliegues en la ventana: un detalle pequeño que provoca errores reales en cuadros de mando los meses tranquilos.

  1. El cuadro de mando inicial de Reservalia

Marta ha dedicado una tarde a reconstruir los datos del último trimestre a partir del historial de Git, del canal del equipo y de las notas de las incidencias. Este es el punto de partida medido —el número más importante de todo el curso, porque es contra el que compararemos todo lo demás:

Métrica Reservalia hoy Nivel orientativo De dónde sale el dato
Frecuencia de despliegue 1,1 por semana Medio 14 despliegues a prod en 13 semanas
Lead time for changes (mediana) 6,2 días Medio Mediana de 47 commits desplegados en el trimestre
Change failure rate 14 % Alto 2 de 14 despliegues provocaron incidencia grave
Time to restore service (mediana) 68 minutos Alto Mediana de las 2 incidencias graves
Fiabilidad (disponibilidad en horario comercial) 99,4 % Por debajo de su objetivo (99,9 %) Registros del balanceador

Y estos son los objetivos que el equipo se fija para el final del curso:

Métrica Hoy Objetivo Palanca principal Módulo
Frecuencia de despliegue 1,1 / semana ≥ 5 / semana Eliminar la ventana del viernes; despliegue automatizado 3
Lead time (mediana) 6,2 días < 4 horas Suprimir la espera; CI rápida; despliegue automático a staging 2 y 3
Change failure rate 14 % < 5 % Pruebas automatizadas en cada PR; lotes pequeños; canary 2 y 3
Time to restore 68 min < 10 min Artefactos inmutables; rollback en un comando; alertas 3
Disponibilidad comercial 99,4 % ≥ 99,9 % Despliegue sin corte; healthchecks; múltiples instancias 3

Tres observaciones sobre estos objetivos que conviene interiorizar:

1. Ninguno persigue la etiqueta "elite". Reservalia no se ha propuesto desplegar veinte veces al día. Se ha propuesto cinco veces por semana, que para ellos es una transformación radical y, sobre todo, alcanzable. Un objetivo que el equipo no cree posible no motiva: desmoraliza.

2. Los objetivos son del equipo, no de personas. Es "el lead time de Reservalia", no "el lead time de Diego". Volveremos sobre esto ahora mismo.

3. Van acompañados de la palanca concreta. Una métrica sin una acción asociada es un termómetro sin medicina. Cada objetivo apunta al módulo donde se trabaja.

graph LR
    subgraph HOY["📍 Punto de partida"]
        H1["1,1 despliegues/semana"]
        H2["6,2 días de lead time"]
        H3["14 % de fallos"]
        H4["68 min de restauración"]
    end
    subgraph MOD["🔧 El curso"]
        M2["Módulo 2<br/>CI: pruebas y artefactos"]
        M3["Módulo 3<br/>CD: despliegue y rollback"]
        M4["Módulo 4<br/>Optimización y seguridad"]
    end
    subgraph META["🎯 Objetivo"]
        O1["≥5 despliegues/semana"]
        O2["<4 h de lead time"]
        O3["<5 % de fallos"]
        O4["<10 min de restauración"]
    end
    HOY --> MOD --> META
    style HOY fill:#ffe8e8
    style META fill:#e8ffe8

  1. La ley de Goodhart: cuando la métrica se convierte en objetivo

Hay una forma infalible de destruir el valor de todo lo anterior, y es tan común que merece su propia sección.

Ley de Goodhart: "Cuando una medida se convierte en objetivo, deja de ser una buena medida."

El mecanismo es siempre el mismo: si de una métrica dependen la evaluación de desempeño, el bonus o el prestigio de alguien, esa persona optimizará la métrica —que es más fácil que optimizar la realidad que la métrica pretendía representar.

12.1. Cómo se manipula cada métrica DORA

Métrica Si se convierte en objetivo individual… Consecuencia real
Frecuencia de despliegue Se trocean cambios artificialmente en diez despliegues vacíos; se despliega el mismo código dos veces El número sube, no llega más valor al usuario, y el ruido dificulta diagnosticar incidentes
Lead time Se hacen commits justo antes de fusionar para "resetear" el reloj; se trabaja en local semanas sin commitear El dato mejora y el tiempo real de entrega empeora, porque las ramas viven más
Change failure rate Se reclasifican incidentes como "mantenimiento programado"; se deja de registrar lo dudoso Los datos dejan de ser reales y se pierde la capacidad de detectar problemas
Time to restore Se declara el servicio restablecido antes de que lo esté; se retrasa la apertura del incidente Los usuarios siguen sufriendo y el panel está verde

Fíjate en el caso del lead time: es especialmente perverso porque la manipulación empeora activamente el proceso. El desarrollador que evita commitear para no "empezar el reloj" está haciendo justo lo contrario de la Integración Continua.

12.2. Reglas para usar las métricas sin destruirlas

  1. Nunca a nivel individual. Son métricas de sistema, no de persona. "El lead time del equipo de Reservalia", jamás "el lead time de Diego". El lead time depende de la velocidad de las revisiones, del proceso de aprobación, de la duración del pipeline y de la ventana de despliegue: casi nada de eso está bajo el control de una sola persona.
  2. Nunca para comparar equipos. Un equipo que mantiene un legacy crítico tendrá siempre peores números que uno que empieza un producto nuevo, y eso no dice nada sobre su competencia. Cada equipo se compara consigo mismo.
  3. Nunca ligadas a retribución o evaluación. Es el camino más corto a datos falsos. En cuanto el bonus depende del número, el número deja de describir la realidad.
  4. Siempre las cuatro juntas. Es la protección estructural. Trocear despliegues para subir la frecuencia empeora el change failure rate; no commitear para bajar el lead time reduce la frecuencia. Mirando las cuatro, las manipulaciones se delatan.
  5. Como herramienta de diagnóstico, no de juicio. El uso correcto es: "nuestro lead time es de 6 días; vamos a averiguar dónde se va el tiempo". El incorrecto es: "nuestro lead time es de 6 días; hay que mejorarlo este trimestre", sin analizar la causa.
  6. Mira la tendencia, no el valor absoluto. Una lectura aislada no dice casi nada. Doce semanas de datos dicen mucho.

12.3. Un antídoto práctico

Cuando presentes las métricas, acompáñalas siempre de la pregunta "¿qué nos impide mejorar esto?" en lugar de "¿por qué está mal esto?". La primera abre una conversación técnica y produce acciones; la segunda produce excusas y, a medio plazo, datos manipulados.

Errores Comunes y Consejos

Error 1: medir el lead time desde que arranca el pipeline. Es el error más frecuente y el que más engaña, porque produce números excelentes. Mide desde la fecha del commit; si no, ocultas justamente el tiempo de espera, que suele ser el problema principal.

Error 2: usar la media en vez de la mediana. Un cambio que se quedó dos meses en una rama olvidada distorsiona la media por completo. La mediana describe el caso típico. Añade el percentil 90 si quieres saber cómo de malo es el peor caso habitual.

Error 3: contar los despliegues a staging. Solo cuenta lo que llega a los usuarios. Es una forma tentadora de inflar la frecuencia de despliegue sin que llegue más valor a nadie.

Error 4: no acordar por escrito qué es un "fallo". Sin una definición explícita en el repositorio, cada persona clasificará los casos dudosos a su manera y la métrica dejará de ser comparable en el tiempo. Acordadla antes de empezar a medir.

Error 5: perseguir la etiqueta "elite". Los umbrales cambian cada año y dependen del contexto. La única comparación que importa es contigo mismo hace tres meses.

Error 6: montar el cuadro de mando antes de tener el pipeline. Es tentador empezar por lo visual. Pero sin despliegues automatizados no hay eventos que registrar, y acabarás rellenando datos a mano, que es exactamente donde se generan los datos falsos. Registra primero, visualiza después.

Error 7: medir sin tener línea base. Si empiezas a medir después de automatizar, no podrás demostrar la mejora. Reconstruir el trimestre anterior a partir del historial de Git y las notas de incidencias, como hizo Marta, es una tarde de trabajo bien invertida.

Consejo 1: registra el evento de despliegue desde el primer pipeline. Es una tabla y una consulta INSERT al final del job. Cinco minutos de trabajo que, seis meses después, valen una conversación entera con dirección.

Consejo 2: guarda el SHA y la fecha del commit en el propio artefacto. Etiquetar la imagen con el SHA y añadir la fecha como etiqueta de metadatos hace que el artefacto sea autodescriptivo: siempre podrás saber qué versión es y cuándo se escribió, aunque la rama ya no exista.

Consejo 3: revisa las métricas en equipo, una vez al mes, sin dirección delante. El objetivo de la reunión es identificar cuellos de botella, no rendir cuentas. En cuanto se percibe como una evaluación, los datos empiezan a degradarse.

Consejo 4: complementa las cuatro con algo cualitativo. Una pregunta trimestral al equipo —"del 1 al 5, ¿cuánta confianza tienes al desplegar a producción?"— captura algo que ninguna de las cuatro mide y que suele anticipar los problemas antes de que aparezcan en los números.

Ejercicios

Ejercicio 1: calcular las cuatro métricas

Estos son los datos reales del último mes de otra empresa, Citalia. Calcula sus cuatro métricas DORA y clasifícalas orientativamente.

Despliegues a producción (mes de marzo, 30 días):

ID Commit Fecha del commit Fecha del despliegue ¿Provocó fallo?
d1 aaa1111 2026-03-02 09:00 2026-03-05 17:00 No
d2 bbb2222 2026-03-04 14:00 2026-03-05 17:00 No
d3 ccc3333 2026-03-06 11:00 2026-03-12 17:00
d4 ddd4444 2026-03-12 18:00 2026-03-12 19:30 No (corrección urgente)
d5 eee5555 2026-03-10 10:00 2026-03-19 17:00 No
d6 fff6666 2026-03-18 16:00 2026-03-19 17:00 No
d7 ggg7777 2026-03-20 09:00 2026-03-26 17:00
d8 hhh8888 2026-03-26 18:00 2026-03-26 20:00 No (corrección urgente)

Incidentes:

ID Inicio (empezó a afectar) Detectado Restablecido
i1 2026-03-12 17:20 2026-03-12 18:05 2026-03-12 19:35
i2 2026-03-26 17:10 2026-03-26 17:25 2026-03-26 20:05

Calcula: frecuencia de despliegue (por semana), lead time mediano (en horas), change failure rate y time to restore mediano. Después, responde: ¿qué patrón revelan estos datos sobre cómo trabaja Citalia?

Ejercicio 2: detectar manipulación de métricas

El nuevo director de tecnología de Citalia ha establecido que el bonus trimestral de cada desarrollador dependerá de "su" lead time individual y de "su" frecuencia de despliegue. Tres meses después, el panel muestra:

  • Frecuencia de despliegue: de 1,9 a 11,3 por semana. 🎉
  • Lead time mediano: de 4,1 días a 3,2 horas. 🎉
  • Change failure rate: de 25 % a 31 %. 😐
  • Time to restore mediano: de 145 min a 210 min. 😟
  • Los desarrolladores comentan que ahora hacen la mayor parte del trabajo en local y solo commitean al final.
  • El número medio de commits por despliegue ha bajado de 4,2 a 1,1, pero el número de líneas cambiadas por despliegue no ha bajado.

Responde:

  1. ¿Han mejorado de verdad? Justifica con los datos.
  2. ¿Qué comportamiento concreto explica cada cifra?
  3. ¿Cuál es el dato que delata la manipulación de forma más clara?
  4. ¿Qué habrías hecho en lugar de ligar el bonus a las métricas?

Ejercicio 3: instrumentar Reservalia

Diseña la instrumentación mínima para que Reservalia empiece a medir hoy, antes de tener ningún pipeline.

  1. ¿Qué eventos hay que registrar como mínimo y en qué momento exacto de cada proceso?
  2. Escribe la consulta SQL que dé el lead time mediano en horas de las últimas 8 semanas para el servicio api en producción.
  3. Reservalia despliega api y web juntas en el mismo acto. ¿Debe registrarse como un despliegue o como dos? Argumenta las dos posturas y decide.
  4. El primer mes solo habrá unos 5 despliegues. ¿Qué precaución hay que tomar al interpretar las métricas con tan pocos datos?

Soluciones

Solución al Ejercicio 1

Frecuencia de despliegue

8 despliegues ÷ 30 días × 7 días = 1,87 despliegues por semana

→ Nivel medio (entre una vez al mes y una vez a la semana, rozando el alto).

Lead time por despliegue

ID Commit Despliegue Lead time
d1 03-02 09:00 03-05 17:00 80 h
d2 03-04 14:00 03-05 17:00 27 h
d3 03-06 11:00 03-12 17:00 150 h
d4 03-12 18:00 03-12 19:30 1,5 h
d5 03-10 10:00 03-19 17:00 223 h
d6 03-18 16:00 03-19 17:00 25 h
d7 03-20 09:00 03-26 17:00 152 h
d8 03-26 18:00 03-26 20:00 2 h

Ordenados: 1,5 · 2 · 25 · 27 · 80 · 150 · 152 · 223

Con 8 valores, la mediana es la media de los dos centrales (4.º y 5.º):

mediana = (27 + 80) / 2 = 53,5 horas ≈ 2,2 días

→ Nivel alto (entre un día y una semana).

Compara con la media: (1,5+2+25+27+80+150+152+223) / 8 = 82,6 h. Un 55 % más alta, arrastrada por los dos valores extremos. Esto ilustra por qué se usa la mediana.

Change failure rate

2 despliegues fallidos (d3 y d7) ÷ 8 despliegues × 100 = 25 %

→ Nivel medio.

Nota importante: d4 y d8 son las correcciones urgentes, no los fallos. No se cuentan como fallidos —ellos arreglaron el problema—, pero sí cuentan en el denominador como despliegues realizados. Contarlos también como fallidos duplicaría el problema en la métrica.

Time to restore service

i1: 03-12 19:35 − 03-12 17:20 = 135 minutos
i2: 03-26 20:05 − 03-26 17:10 = 175 minutos
mediana = (135 + 175) / 2 = 155 minutos ≈ 2,6 horas

→ Nivel alto (menos de un día).

Un detalle que había que notar: la columna "Detectado" no se usa. El tiempo se cuenta desde que el incidente empieza a afectar a los usuarios. Si se midiera desde la detección, i1 daría 90 minutos en vez de 135 —y Citalia estaría premiándose por tener mala monitorización.

¿Qué patrón revelan los datos?

Un patrón muy claro y muy reconocible:

  1. Despliegan los jueves a las 17:00. d1, d2, d3, d5, d6 y d7 son todos jueves a las 17:00. Tienen una ventana de despliegue semanal, exactamente el mismo antipatrón que Reservalia con sus viernes.
  2. El 25 % de sus despliegues son correcciones urgentes (d4 y d8), y ambas ocurren el mismo día que un despliegue fallido, pocas horas después. Es decir: la ventana semanal genera lotes grandes, los lotes grandes rompen producción, y hay que salir de urgencia fuera de la ventana.
  3. La ventana es la causa del lead time alto. Fíjate en el contraste: los despliegues dentro de la ventana tienen lead times de 25 a 223 horas; las correcciones urgentes, de 1,5 y 2 horas. Técnicamente pueden desplegar en 90 minutos. El resto del tiempo es espera pura, autoimpuesta por el proceso.
  4. Los dos incidentes son consecuencia de despliegues. Su problema no es la infraestructura: es cómo entregan.

Conclusión del diagnóstico: la palanca de mejora número uno de Citalia no es comprar herramientas ni escribir más tests. Es eliminar la ventana semanal de los jueves. Ese único cambio atacaría a la vez el lead time, el tamaño del lote y el change failure rate.

Solución al Ejercicio 2

1. ¿Han mejorado de verdad?

No. Han mejorado las dos métricas de velocidad (las que afectan al bonus) y han empeorado las dos de estabilidad (las que no). Ese patrón exacto —velocidad arriba, estabilidad abajo— es la firma clásica de la manipulación, y es justamente lo que el conjunto de cuatro métricas está diseñado para revelar.

Recuerda el hallazgo central de la sección 1: en una mejora real, velocidad y estabilidad mejoran juntas. Cuando divergen en direcciones opuestas, no estás viendo una mejora: estás viendo cómo se optimiza el indicador a costa de lo que el indicador debía representar.

2. Qué comportamiento explica cada cifra

Cifra Comportamiento que la produce
Frecuencia ×6 Se trocean los cambios en despliegues artificiales para que cada desarrollador acumule despliegues propios
Lead time de 4,1 días a 3,2 h Se trabaja en local durante días y se commitea justo antes de fusionar: el reloj empieza tarde. El tiempo real de entrega no ha bajado; solo ha bajado la parte que se mide
Change failure rate 25 % → 31 % Más despliegues sin más verificación; y, sobre todo, código que ha estado días sin integrarse (integration hell de 01-01) llega de golpe
Time to restore 145 → 210 min Con más despliegues fragmentados y menos integración, diagnosticar qué rompió qué es más difícil. Además, nadie tiene incentivo en restaurar rápido: no puntúa

3. El dato que delata la manipulación

El número de commits por despliegue baja de 4,2 a 1,1 mientras las líneas cambiadas por despliegue se mantienen.

Este dato es demoledor y merece pararse en él. Si los lotes fueran realmente más pequeños, ambas cifras habrían bajado: menos commits y menos líneas por despliegue. Que las líneas no bajen significa que se está entregando la misma cantidad de cambio, empaquetada en menos commits. Es decir: la gente acumula trabajo en local y lo suelta en un único commit gigante justo antes de fusionar.

Eso es exactamente lo contrario de la Integración Continua, y explica de forma coherente las cuatro cifras a la vez: ramas más longevas → integración más tardía → más conflictos y menos verificación → más fallos → diagnósticos más lentos.

4. Qué habría que haber hecho

  • No ligar nunca las métricas a la retribución ni a la evaluación individual. Es la regla que se ha roto y de la que se deriva todo lo demás.
  • Medir a nivel de equipo o de servicio, nunca de persona. El lead time depende de la velocidad de las revisiones, de los procesos de aprobación y de la ventana de despliegue: casi nada de eso lo controla un individuo.
  • Usar las métricas para diagnosticar, no para juzgar. El análisis del ejercicio 1 mostraba que el problema de Citalia era la ventana semanal de los jueves. La acción correcta era eliminarla, no repartir bonus.
  • Presentar siempre las cuatro juntas. Si el panel del director hubiera mostrado las cuatro desde el principio, la divergencia habría saltado a la vista en la primera revisión mensual.
  • Fijar objetivos de sistema, no de persona. "Reducir el lead time del equipo por debajo de 8 horas eliminando la ventana de despliegue" es un objetivo accionable y compartido. "Que cada desarrollador baje su lead time" no lo es.

Solución al Ejercicio 3

1. Eventos mínimos y momento exacto

Evento Cuándo se registra exactamente Campos imprescindibles
Despliegue a producción Como último paso del proceso de despliegue, solo si ha terminado con éxito id, servicio, entorno, commit_sha, commit_fecha, desplegado_en, commits_incluidos
Marca de despliegue fallido Durante el incidente, en cuanto se identifica el despliegue culpable despliegue_id, fallido = true, motivo
Apertura de incidente Cuando se determina la hora en que empezó a afectar a los usuarios (no la de detección) id, servicio, inicio, severidad, despliegue_id si aplica
Cierre de incidente Cuando el servicio vuelve a funcionar para los usuarios (no cuando se entiende la causa) restablecido

Detalle crítico: commit_fecha debe capturarse en el momento del despliegue con git show -s --format=%cI, no consultarse después. Las ramas se borran y los historiales se reescriben.

Mientras no exista pipeline, estos eventos se registran a mano con un script de dos líneas ejecutado por quien despliega. No es elegante, pero produce datos reales desde hoy, que es lo que importa.

2. Consulta SQL

SELECT
  ROUND(
    PERCENTILE_CONT(0.5) WITHIN GROUP (
      ORDER BY EXTRACT(EPOCH FROM (desplegado_en - commit_fecha))
    ) / 3600.0, 1
  ) AS lead_time_mediana_horas,
  COUNT(*) AS n_despliegues            -- imprescindible para saber si el dato vale
FROM despliegues
WHERE servicio      = 'api'
  AND entorno       = 'prod'
  AND resultado     = 'exito'
  AND desplegado_en >= now() - interval '8 weeks';

El COUNT(*) no es opcional: una mediana calculada sobre 5 despliegues no debe presentarse igual que una calculada sobre 200.

3. ¿Un despliegue o dos?

A favor de registrarlo como dos (uno por servicio):

  • Es lo que recomienda el marco DORA: la unidad de medida es el servicio desplegable.
  • Permite ver si un servicio evoluciona distinto del otro (por ejemplo, si la web se despliega más a menudo cuando se independicen).
  • Si en el futuro se separan —cosa muy probable—, la serie histórica sigue siendo comparable.

A favor de registrarlo como uno:

  • Refleja la realidad actual: hoy no se pueden desplegar por separado, así que dos filas sugieren una independencia que no existe.
  • Duplicaría artificialmente la frecuencia de despliegue, haciendo que Reservalia parezca el doble de rápida de lo que es.

Decisión: registrar dos filas, una por servicio, pero con un campo grupo_despliegue común que las vincule. Así se conserva la granularidad por servicio para el futuro y, a la vez, se puede calcular la frecuencia contando grupos distintos en lugar de filas, sin inflar el número. Es la opción que no destruye información y que no engaña.

-- Frecuencia REAL de despliegue (actos de despliegue, no filas)
SELECT COUNT(DISTINCT grupo_despliegue) FROM despliegues
WHERE entorno = 'prod' AND resultado = 'exito';

4. Precauciones con pocos datos

  • Con 5 despliegues, la mediana es muy inestable. Un solo valor extremo la desplaza por completo. No tomes decisiones basándote en la variación de un mes a otro.
  • El change failure rate es especialmente engañoso. Con 5 despliegues, cada fallo vale un 20 %: pasar de 0 % a 20 % suena a catástrofe y es un solo incidente. Con estos volúmenes, es más informativo reportar el número absoluto ("1 de 5") que el porcentaje.
  • Usa ventanas más largas. Con poco volumen, agrega por trimestre en lugar de por semana, o usa medias móviles de 90 días.
  • Muestra siempre el tamaño de la muestra junto a cada métrica. Un panel que dice "change failure rate: 20 %" sin decir "(1 de 5)" invita a conclusiones equivocadas.
  • Fíjate en la tendencia, no en el valor puntual. Con pocos datos, la dirección del movimiento a lo largo de varios meses es mucho más fiable que cualquier cifra concreta.
  • Y algo tranquilizador: a medida que Reservalia avance en el curso, la frecuencia de despliegue subirá, y con ella el volumen de datos. Las métricas se vuelven más fiables precisamente a medida que el proceso mejora.

Conclusión

Con esta lección cerramos el módulo de introducción, y lo hacemos con lo que probablemente sea la herramienta más práctica de todo el módulo:

  • Las cuatro métricas DORA —frecuencia de despliegue, lead time for changes, change failure rate y time to restore service— resumen el rendimiento de la entrega en dos parejas que se equilibran: velocidad y estabilidad. Su gran virtud es que no se pueden manipular a la vez.
  • El hallazgo que cambia la forma de pensar: velocidad y estabilidad van juntas. Desplegar más a menudo obliga a lotes pequeños, y los lotes pequeños fallan menos y se diagnostican antes.
  • La quinta métrica, la fiabilidad, mide el resultado operativo mediante objetivos de nivel de servicio propios de cada equipo, y evita el espejismo de tener las cuatro en verde con un servicio malo.
  • Cada dato sale de un evento concreto: la frecuencia y el lead time, del job de despliegue y de la fecha del commit; el change failure rate, de una marca humana durante el incidente; el time to restore, de la gestión del incidente. Todo cabe en dos tablas y unas pocas consultas SQL: no hace falta comprar nada.
  • Los rangos de rendimiento son referencias que se mueven cada año y dependen del contexto. La única comparación que importa es contigo mismo hace tres meses.
  • Reservalia ya tiene su línea base medida: 1,1 despliegues por semana, 6,2 días de lead time, 14 % de cambios fallidos y 68 minutos de restauración. Y sus objetivos para el final del curso: 5 despliegues semanales, menos de 4 horas, menos del 5 % y menos de 10 minutos.
  • Y la advertencia que sostiene todo lo demás: la ley de Goodhart. En cuanto una métrica se convierte en objetivo individual —ligado a evaluaciones o bonus—, deja de describir la realidad. Son métricas de sistema, sirven para diagnosticar, y se miran las cuatro juntas.

Con esto termina el módulo 1. Ya sabes qué son la Integración Continua, la Entrega Continua y el Despliegue Continuo y en qué se diferencian; conoces los beneficios reales y los costes que nadie menciona; tienes el mapa del ecosistema de herramientas y sabes por qué usaremos GitHub Actions; conoces a fondo Reservalia, su equipo, su repositorio y su infraestructura de destino; y tienes el cuadro de mando que nos dirá, dentro de siete módulos, si todo esto ha servido de algo.

Se acabó la teoría. En el módulo 2, Integración Continua (CI), empezamos a construir: la primera lección, Introducción a la Integración Continua, sienta las reglas de trabajo del equipo —qué es la rama principal, cuánto puede vivir una rama, qué pasa cuando la build se pone roja— y en la lección 02-02 escribiremos, por fin, el primer workflow real de Reservalia. Diego dejará de compilar en su portátil: a partir de ahí, cada cambio se verifica solo, en una máquina limpia, antes de que nadie lo fusione.

Curso de CI/CD: Integración y Despliegue Continuo

Módulo 1: Introducción a CI/CD

Módulo 2: Integración Continua (CI)

Módulo 3: Despliegue Continuo (CD)

Módulo 4: Prácticas Avanzadas de CI/CD

Módulo 5: Implementación de CI/CD en Proyectos Reales

Módulo 6: Herramientas y Tecnologías

Módulo 7: Ejercicios Prácticos

Módulo 8: Recursos Adicionales

© Copyright 2026. Todos los derechos reservados