Reservalia ja desplega sola, amb entorns reproduïbles, una estratègia de relleu triada a consciència i un botó de tornada enrere assajat. I tanmateix continua tenint un forat al centre: s'assabenta que producció va malament perquè truca un client. Els 3 minuts de detecció que prometia la taula de la lliçó anterior encara no existeixen, comprovar-metriques.sh invoca uns llindars que ningú no ha definit, i el freeze dels divendres continua dret perquè ningú no té un argument objectiu per retirar-lo. Sense senyal de producció, el desplegament continu és simplement desplegar a cegues més de pressa. Aquesta lliçó tanca el bucle —i amb ell, el mòdul—: què observar, com convertir aquelles observacions en objectius amb conseqüències, quan val la pena despertar algú, i com el mateix pipeline s'alimenta del que passa a producció.
Contingut
- El bucle obert: per què el CD sense monitoratge és una aposta ràpida
- Els tres pilars de l'observabilitat
- Els quatre senyals d'or aplicats a l'API de Reservalia
- El panell mínim de Reservalia
- SLI, SLO i pressupost d'error
- La política de pressupost: adeu al freeze dels divendres
- Marcar els desplegaments als panells
- Alertes: símptomes, no causes
- Retroalimentació cap al pipeline: les mètriques DORA s'alimenten soles
- El quadre de comandament de Reservalia després dels mòduls 2 i 3
- Errors Comuns i Consells
- Exercicis
- Conclusió
- El bucle obert: per què el CD sense monitoratge és una aposta ràpida
Tot el que hem construït fins aquí forma una cadena que empeny canvis cap a producció cada vegada més de pressa. El que falta és la fletxa de tornada.
flowchart LR
C["commit"] --> CI["ci.yml"] --> CD["cd.yml"] --> P["prod"]
P -->|"?"| S["Senyal:<br/>funciona per als negocis?"]
S -.->|"decideix si es continua desplegant"| C
S -.->|"dispara rollback"| CD
S -.->|"alimenta les metriques DORA"| M["Quadre de comandament"]
Sense aquella fletxa passen tres coses concretes, totes visibles a Reservalia avui: el canary de la 03-04 no pot decidir si promociona, perquè comprovar-metriques.sh no té contra què comparar; el rollback de la 03-05 arriba tard, perquè la detecció depèn que un client truqui; i l'equip manté el freeze dels divendres perquè la seva única alternativa a la prudència cega seria la temeritat cega.
Convé distingir dues paraules que es fan servir com a sinònimes. Monitorar és vigilar coses que ja saps que poden fallar: la CPU, la memòria, el nombre d'errors. Observabilitat és la propietat d'un sistema que permet respondre preguntes que no havies anticipat: "per què les reserves dels negocis amb horari partit triguen quatre segons només els dilluns?". La primera es configura; la segona es dissenya, instrumentant el codi perquè emeti prou context.
- Els tres pilars de l'observabilitat
| Pilar | Què és | Quina pregunta respon | Cost | A Reservalia |
|---|---|---|---|---|
| Mètriques | Números agregats en el temps | Hi ha un problema? Com de gran? | Baix i constant | CloudWatch: latència, 5xx, tasques sanes |
| Logs | Esdeveniments discrets amb context | Què ha passat exactament en aquesta petició? | Alt: creix amb el trànsit | CloudWatch Logs, JSON estructurat |
| Traces | El recorregut d'una petició pel sistema | On se n'ha anat el temps? | Mitjà, amb mostreig | OpenTelemetry (pendent) |
L'ordre importa i és l'ordre d'una investigació: la mètrica t'avisa, la traça et localitza, el registre t'ho explica. Un equip que només té logs se n'assabenta tard i busca a cegues; un que només té mètriques sap que alguna cosa va malament però no per què.
Reservalia fa una inversió petita que multiplica el valor dels seus logs: emetre'ls en JSON estructurat amb camps fixos.
// apps/api/src/log.ts — un registre que es pot consultar, no nomes llegir
export function log(nivell: 'info' | 'error', missatge: string, extra: Record<string, unknown> = {}) {
console.log(JSON.stringify({
ts: new Date().toISOString(),
nivell,
missatge,
commit: process.env.COMMIT_SHA, // 1 · quina versio ha emes aquesta linia
entorn: process.env.ENTORN,
...extra, // 2 · negociId, rutaId, duracioMs…
}));
}- Incloure el commit a cada línia és el que permet, durant un incident, filtrar els errors per versió i comprovar en deu segons si van començar amb el desplegament de les 09:08. És la mateixa idea de l'endpoint
/version, aplicada als logs. - Camps estructurats en lloc de text interpolat.
log('error', 'reserva fallida', { negociId: 412, duracioMs: 3140 })es pot agregar i filtrar;console.log('Error en la reserva del negoci 412')només es pot llegir. La regla: no fiquis mai una dada variable dins del text del missatge.
Un advertiment de cost que sorprèn molts equips: els logs són el pilar que més creix i més factura. Reservalia registra en info les operacions de negoci (reserva creada, cancel·lada) i en error les fallades, però no una línia per petició HTTP: per a això hi ha les mètriques, que costen una fracció.
- Els quatre senyals d'or aplicats a l'API de Reservalia
Els quatre senyals d'or són el conjunt mínim que respon "el meu servei està bé?" per a gairebé qualsevol sistema amb peticions.
| Senyal | Què mesura | Mètrica concreta a Reservalia | Llindar de referència |
|---|---|---|---|
| Latència | Quant triga a respondre | p50, p95 i p99 de POST /api/reserves |
p95 < 400 ms |
| Trànsit | Quanta demanda hi ha | Peticions/minut a l'ALB; reserves creades/hora | Context, no alarma |
| Errors | Quina fracció falla | Proporció de respostes 5xx sobre el total | < 0,1 % |
| Saturació | Com de ple està el sistema | CPU i memòria de les tasques ECS; connexions lliures del pool de RDS | CPU < 70 %, pool < 80 % |
Tres precisions que separen un panell útil d'un de decoratiu:
La latència es mesura en percentils, mai en mitjana. Si 99 peticions triguen 100 ms i una triga 10 segons, la mitjana és de 199 ms —un número tranquil·litzador que amaga un usuari que ha marxat—. El p95 diu "el 95 % dels usuaris espera menys que això", i el p99 és on viuen els casos rars que acaben al xat de suport. A més, la latència dels errors s'ha de mesurar a part: un servei que comença a retornar 500 en dos mil·lisegons millora la seva latència mitjana mentre cau.
El trànsit gairebé mai no és una alarma, però és imprescindible com a context. Un error rate del 5 % amb 20.000 peticions i amb 40 peticions són incidents de gravetat molt diferent, i una caiguda del trànsit a zero pot ser l'únic senyal que el frontal està trencat encara que l'API respongui perfectament.
La saturació és l'únic senyal que avisa abans. Latència, errors i trànsit descriuen el que ja està passant; el pool de connexions al 85 % diu que d'aquí a vint minuts hi haurà un incident. És el senyal que permet actuar en lloc de reaccionar.
- El panell mínim de Reservalia
La Nuria crea un únic panell, reservalia-api-prod, amb la regla que ha de cabre en una pantalla i respondre en deu segons a la pregunta "està bé?".
| Fila | Widgets | Per què hi és |
|---|---|---|
| 1 · Estat | Peticions/min · % de 5xx · p95 global · tasques sanes / desitjades | El semàfor: quatre números que resumeixen la salut |
| 2 · Camí crític | p95 i errors de POST /api/reserves i de GET /forats |
El negoci és reservar; la resta és secundari |
| 3 · Dependències | Latència d'RDS · connexions lliures del pool · errors del proveïdor d'SMS | On sol ser la causa real |
| 4 · Pressupost | Pressupost d'error consumit aquest mes · versió desplegada per entorn | La decisió de si es pot continuar desplegant |
// apps/api/src/middleware/metriques.ts — una metrica per peticio, sense llibreria pesada
app.use((req, res, next) => {
const inici = process.hrtime.bigint();
res.on('finish', () => {
const ms = Number(process.hrtime.bigint() - inici) / 1e6;
emetreMetrica({
nom: 'ApiLatencia',
valor: ms,
unitat: 'Milliseconds',
dimensions: { // 1
ruta: req.route?.path ?? 'desconeguda',
metode: req.method,
classe: `${Math.floor(res.statusCode / 100)}xx`,
},
});
});
next();
});- Les dimensions són la clau i també el parany. Permeten filtrar per ruta, mètode i classe de resposta, que és justament el que cal per saber si el problema és general o d'un endpoint. Però cada combinació diferent de dimensions és una mètrica facturable: fer servir
req.pathen lloc dereq.route.pathcrearia una mètrica per cada/api/negocis/412/forats, és a dir, una per negoci, amb una factura de tres xifres i panells inservibles. No facis servir mai identificadors com a dimensió.
- SLI, SLO i pressupost d'error
Un panell et diu com està el sistema; no et diu si allò és acceptable. Per a això calen tres conceptes encadenats.
| Concepte | Què és | Exemple a Reservalia |
|---|---|---|
| SLI (indicador) | Una mesura concreta de l'experiència de l'usuari | % de peticions a l'API que no retornen 5xx |
| SLO (objectiu) | El valor que aquell indicador ha d'assolir en una finestra | ≥ 99,9 % en 30 dies naturals |
| SLA (acord) | Un SLO amb conseqüències contractuals | No aplica: Reservalia no signa penalitzacions |
| Pressupost d'error | El que sobra fins al 100 %: fallada permesa | 0,1 % de les peticions del mes |
Reservalia defineix dos SLO, i només dos. La temptació de definir-ne quinze és forta i és un error: un SLO que ningú no mira no disciplina res.
| SLO | SLI | Objectiu | Finestra | Pressupost |
|---|---|---|---|---|
| Disponibilitat | Peticions sense 5xx / peticions totals | 99,9 % | 30 dies | 0,1 % ≈ 43 min de caiguda total |
| Latència de reserva | Peticions a POST /api/reserves servides en < 400 ms |
99,0 % | 30 dies | 1 % de les reserves |
Tres decisions de disseny mereixen explicació. Es mesura des del punt de vista de l'usuari, no del servidor: l'SLI compta peticions que van arribar a l'ALB, incloses les que van fallar perquè no hi havia cap tasca sana; mesurar només el que l'aplicació va aconseguir processar és posar-se un mateix la nota. L'objectiu no és el 100 %, i això és el que més costa acceptar: el 100 % és impossible (falla la xarxa, falla AWS, falla el client) i indesitjable, perquè el cost de cada nou nou es multiplica i aquells diners surten de construir producte. 99,9 % en 30 dies són 43 minuts de pressupost, que és exactament el material amb què es compra la capacitat de desplegar de pressa.
Perquè aquesta és la idea central: el pressupost d'error no és un mal que cal evitar, és un recurs que cal gastar. Un equip que acaba el mes amb el 100 % del pressupost intacte no ha estat excel·lent: ha estat massa conservador, ha desplegat menys del que podia i ha lliurat menys valor del que podia. Un equip que l'exhaureix el dia 12 té un problema de fiabilitat. L'objectiu és arribar a final de mes havent-lo gastat gairebé tot.
- La política de pressupost: adeu al freeze dels divendres
A la lliçó 03-01 vam deixar el freeze dels divendres qualificat com a deute tècnic, amb data de retirada i condicions. El pressupost d'error és la regla objectiva que el substitueix, perquè respon a la mateixa preocupació —"no vull trencar producció en mal moment"— amb dades en lloc de amb calendari.
| Pressupost restant | Què es pot fer | Qui decideix |
|---|---|---|
| > 50 % | Desplegar amb normalitat, qualsevol dia de la setmana | El pipeline, sense intervenció |
| 25 – 50 % | Es continua desplegant, però la fiabilitat entra a la planificació del sprint | Marta |
| 10 – 25 % | Només correccions, canvis de fiabilitat i feina de baix risc | Marta + Nuria |
| < 10 % | Congelació de funcionalitats: tot l'equip a fiabilitat fins a recuperar | Acordat per endavant |
Les tres propietats que fan que això funcioni millor que un freeze:
- És objectiu. No depèn que avui algú estigui nerviós. La regla s'acorda quan ningú no és en un incident, que és l'únic moment en què es pensa amb claredat.
- És simètric. Si la fiabilitat va bé, l'equip guanya llibertat: es desplega el divendres a les cinc. El freeze només restringia; el pressupost també premia.
- Alinea tothom. Producte deixa de demanar "més funcionalitats i també més estabilitat" com si fossin independents: el pressupost fa explícit que són la mateixa moneda.
Reservalia retira el freeze dels divendres el dia que es compleixen les tres condicions que la 03-01 va deixar escrites —rollback demostrat en un simulacre cronometrat, detecció automàtica d'incidents greus, i un historial d'aprovacions que no filtrava res— i el substitueix per aquesta taula. La primera setmana sense freeze, en Diego fusiona un canvi un divendres a les 16:40; el canary el promociona a les 17:10 i no passa absolutament res. Aquell no-esdeveniment és el resultat del mòdul sencer.
- Marcar els desplegaments als panells
La pregunta que es fa un equip davant d'una degradació és sempre la mateixa: això ha començat amb l'últim desplegament? Respondre-la mirant dues pestanyes i comparant marques de temps és lent i propens a error. La solució és barata: anotar cada desplegament sobre les gràfiques.
# cd.yml, despres del smoke test de prod
- name: Anotar el desplegament al panell
run: |
aws cloudwatch put-metric-data --namespace Reservalia/Desplegaments \
--metric-name Desplegament --value 1 \
--dimensions Entorn=prod,Commit=${{ steps.meta.outputs.sha }}Amb aquella mètrica superposada com a línia vertical sobre les gràfiques de latència i errors, la correlació es veu d'un cop d'ull: si la corba es torça just a la línia, el sospitós està identificat; si es va torçar vint minuts abans, el desplegament és innocent i cal mirar cap a les dependències. És el mateix raonament que vam aplicar als logs amb el camp commit, portat a les gràfiques, i és el que fa que la primera pregunta d'un incident es respongui en segons en lloc de en deu minuts.
Un matís honest: correlació no és causalitat. Un desplegament coincident pot ser casualitat —a les 09:00 es desplega i comença el pic de trànsit matinal—. L'anotació no tanca la investigació; la comença pel lloc correcte.
- Alertes: símptomes, no causes
Una alerta ha de complir tres condicions: és real (no soroll), és urgent (no pot esperar a demà) i és accionable (qui la rep pot fer alguna cosa). Si en falla alguna, no és una alerta: és un correu.
La distinció fonamental és entre alertar sobre causes i alertar sobre símptomes.
| Alerta per causa | Alerta per símptoma | |
|---|---|---|
| Exemple | "CPU de la tasca al 91 %" | "El 3 % de les reserves falla" |
| Problema | Pot no afectar ningú; hi ha infinites causes possibles | — |
| Avantatge | — | Cobreix causes que ningú no va anticipar, inclosa la que fallarà demà |
| Quan serveix | Com a predicció amb marge (disc al 85 %) | Sempre: és la referència |
Alertar per causes produeix el pitjor dels mons: moltes notificacions que no signifiquen res per a l'usuari i, tot i així, forats —el dia que el sistema falla per un motiu que ningú no va preveure, no hi ha alerta—. Reservalia defineix tres alertes i ni una més:
| Alerta | Condició | Gravetat | Acció |
|---|---|---|---|
ApiErrors5xx |
> 1 % de 5xx durant 5 min a prod |
Desperta | Mirar el desplegament recent, mitigar |
ApiLatenciaReserves |
p95 de POST /api/reserves > 1 s durant 10 min |
Desperta | Igual: és un símptoma d'usuari |
PressupostConsumRapid |
Es consumeix el 10 % del pressupost mensual en 1 h | Desperta | Incident en curs, encara que el percentatge total sigui bo |
PoolConnexionsAlt |
Connexions lliures < 20 % durant 15 min | Tiquet | Revisar en horari laboral |
FlagsCaducats |
Hi ha flags de release vençuts | Tiquet setmanal | Retirar deute (03-05) |
La tercera mereix un comentari, perquè és la més sofisticada. Un SLO mensual té un problema: si el sistema cau del tot un dia 2, el percentatge mensual acumulat encara es veu bé durant hores i no salta res. La velocitat de consum del pressupost —burn rate— mesura quant s'està gastant ara, i detecta en minuts una caiguda que el percentatge mensual trigaria un dia a reflectir. És l'alerta que converteix un SLO en una cosa operativa i no només en un informe.
Sobre la fatiga d'alertes: és la fallada més comuna i la més cara, perquè no es manifesta com un incident sinó com una lenta pèrdua de confiança. Un equip que rep trenta notificacions al dia deixa de llegir-les —no per indisciplina, sinó perquè és humanament inevitable— i el dia que arriba la important, es perd entre les altres. Tres regles d'higiene: si una alerta no ha requerit cap acció les últimes cinc vegades, s'esborra o es converteix en tiquet; tota alerta que desperta porta enllaç a un procediment escrit amb els tres primers passos; i el nombre d'alertes que desperten es revisa cada mes i ha de tendir a la baixa.
La prova definitiva abans de crear una alerta que soni de matinada: què faria una persona a les 3:40 en rebre-la? Si la resposta és "mirar-la i tornar-se a adormir", aquella alerta no ha d'existir.
- Retroalimentació cap al pipeline: les mètriques DORA s'alimenten soles
A la lliçó 01-05 vam construir el quadre de comandament DORA amb les taules desplegaments i incidents, emplenades a mà. Un quadre de comandament que depèn que algú recordi escriure una fila està desactualitzat en tres setmanes. Ara que el pipeline coneix cada desplegament i les alertes coneixen cada incident, totes dues taules es poden omplir soles.
# cd.yml, ultim pas del job de prod
- name: Registrar el desplegament
if: always() # 1
run: |
psql "$DATABASE_URL_METRIQUES" <<SQL
INSERT INTO desplegaments
(entorn, commit_sha, iniciat_el, acabat_el, exit, run_id, primer_commit_el)
VALUES
('prod', '${{ steps.meta.outputs.sha }}',
'${{ steps.meta.outputs.inici }}', now(),
${{ job.status == 'success' }},
'${{ github.run_id }}', -- 2
'${{ steps.meta.outputs.data_primer_commit }}') -- 3
ON CONFLICT (run_id, entorn) DO NOTHING; -- 4
SQLif: always()registra també els desplegaments fallits. Sense ells, el change failure rate mesuraria només els èxits i donaria sempre 0 %, que és la manera més comuna de tenir una mètrica preciosa i inútil.run_idenllaça la fila amb l'execució de GitHub Actions: des del quadre de comandament s'arriba als logs en un clic.data_primer_commités el que permet calcular el lead time de debò, que es mesura des que es va escriure el codi i no des que va començar el desplegament. S'obté ambgit log -1 --format=%cIsobre el commit més antic del PR.ON CONFLICT DO NOTHINGfa la inserció idempotent, com exigia la 03-02: rellançar el workflow no duplica la fila ni contamina les mètriques.
Els incidents es registren igual, des de l'alerta i des del mateix rollback.yml de la 03-05, que ja rebia un motiu obligatori precisament per a això. Amb les dues taules al dia, les quatre mètriques són consultes:
-- Frequencia de desplegament i change failure rate dels ultims 30 dies
SELECT
count(*) FILTER (WHERE exit) / 4.3 AS desplegaments_per_setmana,
round(100.0 * count(*) FILTER (WHERE NOT exit) / count(*), 1) AS pct_fallits,
round(avg(extract(epoch FROM acabat_el - primer_commit_el) / 3600)::numeric, 1) AS lead_time_hores
FROM desplegaments
WHERE entorn = 'prod' AND acabat_el > now() - interval '30 days';Una precisió metodològica sobre el change failure rate: no compta els desplegaments que van fallar al pipeline —aquests són bones notícies, el sistema va fer la seva feina—, sinó els que van arribar a producció i es van haver d'arreglar o revertir. La manera pràctica de mesurar-ho és comptar els desplegaments seguits d'un rollback o d'un incident en les 24 hores següents, que és justament el que permet creuar desplegaments amb incidents.
- El quadre de comandament de Reservalia després dels mòduls 2 i 3
Aquest és el resultat de la feina de dos mòduls, mesurat amb la mateixa vara de la línia base:
| Mètrica DORA | Línia base | Objectiu | Ara | Què ho ha aconseguit |
|---|---|---|---|---|
| Freqüència de desplegament | 1,1 / setmana | ≥ 5 / setmana | 12 / setmana ✅ | cd.yml automàtic; sense freeze |
| Lead time for changes | 6,2 dies | < 4 h | 3,5 h ✅ | PR petits, CI de 4 min, desplegament de 30 min |
| Change failure rate | 14 % | < 5 % | 6,5 % ⚠️ | Quality gate, canary i circuit breaker |
| Time to restore | 68 min | < 10 min | 9 min ✅ | Alertes, flags i rollback.yml |
Tres de quatre objectius complerts, i el quart a mig camí. Val la pena mirar per què s'ha encallat el change failure rate, perquè la resposta no és en aquest mòdul: les fallades que queden no són de desplegament, són de contingut —una dependència que va canviar de comportament en una actualització menor, una migració d'esquema que va bloquejar una taula en horari laboral, un cas de negoci que les proves no cobrien—. Això és exactament el que aborda el mòdul següent.
I hi ha una millora que cap taula no recull. El ritual del divendres de la lliçó 01-04 —tres hores de SFTP, migracions a mà a psql, en Diego mirant logs— ha desaparegut. No s'ha optimitzat: ha deixat d'existir com a categoria de feina. La Marta, en Diego i la Nuria dediquen aquell temps a una altra cosa, i aquest és el benefici real que les quatre mètriques només insinuen.
El que queda pendent, i que dona forma al mòdul 4:
- El pipeline és lent i s'està engreixant. La CI triga 4 minuts avui; amb més proves seran 15, i en Diego deixarà de mirar-la. Calen memòria cau, paral·lelisme i execució selectiva.
- Les dependències no estan sota control. Ningú no sap quants paquets transitius entren a
reservalia/api, ni qui els manté, ni quina versió exacta es va fer servir aa3f9c21. - El pipeline té permisos sobre producció i no s'ha auditat. Des de la 03-01 sabem que va deixar de ser una eina interna per convertir-se en un sistema crític, i continua sense anàlisi de seguretat, signatura d'artefactes ni inventari de components.
- Les migracions de base de dades continuen sent el punt fràgil. Són l'única raó per la qual el rollback de la 03-05 pot no funcionar.
Diego: "Si la CI triga més que anar a buscar un cafè, deixo de mirar-la. I ara que el desplegament és meu fins a producció, la miro molt més."
Errors Comuns i Consells
Error 1: mesurar la mitjana en lloc de percentils. Amaga exactament els usuaris que ho estan passant pitjor. Error 2: alertar sobre causes. Produeix soroll i, alhora, forats davant de fallades no anticipades.
Error 3: definir quinze SLO. Un SLO que ningú no consulta no disciplina res; dos que es miren cada setmana canvien el comportament de l'equip. Error 4: posar l'objectiu al 100 %, cosa que fa el pressupost igual a zero i converteix qualsevol desplegament en una violació.
Error 5: fer servir identificadors com a dimensió d'una mètrica. Un negociId com a dimensió multiplica el cost per 340 i fa el panell il·legible. Error 6: panells que ningú no mira, construïts amb tot el que l'eina oferia en lloc de amb el que respon una pregunta.
Error 7: registrar només els desplegaments amb èxit. El change failure rate sortirà sempre estupend i no significarà res.
Consell 1: defineix els SLO amb producte, no només amb enginyeria. L'objectiu de fiabilitat és una decisió de negoci disfressada de decisió tècnica. Consell 2: acorda la política de pressupost per escrit i en fred, abans del primer incident que la posi a prova. Consell 3: revisa les alertes una vegada al mes i esborra sense pietat les que no han provocat cap acció.
Exercicis
Exercici 1
El panell de Reservalia mostra un p95 estable en 180 ms durant tota la setmana, però suport reporta tres negocis que es queixen de lentitud en obrir l'agenda. L'equip respon que "les mètriques estan bé". Explica què pot estar passant i quins tres canvis faries a la instrumentació.
Exercici 2
És dia 18 del mes. El pressupost d'error de disponibilitat està consumit al 78 % per una caiguda d'RDS del dia 6. Producte demana desplegar una funcionalitat gran aquesta setmana. Aplica la política de l'apartat 6, argumenta la decisió i explica què faries si producte insisteix amb un motiu de negoci legítim.
Exercici 3
Dissenya l'alerta que detectaria, en menys de cinc minuts, un desplegament que provoca que el 100 % de les reserves d'un sol negoci gran falli, mentre la resta de negocis funciona amb normalitat. Discuteix per què les tres alertes actuals de Reservalia probablement no ho detectarien.
Solucions
Solució 1. El més probable és que les mètriques estiguin ben mesurades i mal agregades. Un p95 global sobre totes les rutes barreja milers de peticions barates (/salut, llistats en memòria cau) amb les cares: si el 92 % del trànsit respon en 30 ms, hi ha marge de sobres perquè un endpoint concret trigui uns quants segons sense moure el p95 global. A més, tres negocis sobre 340 són menys de l'1 % del trànsit: per definició viuen al p99, invisibles al p95. I hi ha una tercera possibilitat: que la lentitud sigui al frontal —descàrrega de recursos, renderitzat— i l'API no la vegi en absolut.
Els tres canvis: (1) mesurar percentils per ruta, no només globals, i portar al panell el p95 i el p99 de les rutes del camí crític; (2) afegir el p99 al costat del p95, perquè els problemes que reporta suport viuen allà, i complementar-ho amb logs estructurats que registrin les peticions per sobre d'un llindar (per exemple, 1 s) amb el seu negociId, cosa que permetria descobrir en un minut que els tres negocis afectats són els que tenen horari partit i 400 cites setmanals; (3) instrumentar el client (Real User Monitoring) per mesurar el que experimenta el navegador, que és l'única cosa que l'usuari percep. La lliçó de fons: un SLI que no representa l'experiència de l'usuari és un número que tranquil·litza sense informar.
Solució 2. Amb el 78 % consumit queda el 22 %, així que la política situa Reservalia a la franja de 10-25 %: només correccions, canvis de fiabilitat i feina de baix risc. La decisió per defecte és no desplegar la funcionalitat gran aquesta setmana, i la conversa amb producte no hauria de ser una negociació de voluntats sinó l'aplicació d'una regla acordada prèviament.
Ara bé, hi ha un matís tècnic important i honest: el pressupost es va exhaurir per una caiguda d'RDS aliena als desplegaments, no per canvis de l'equip. Bloquejar el lliurament per un incident d'infraestructura castiga la conducta equivocada, i una política que es percep injusta s'acaba ignorant. Dues sortides legítimes: revisar si aquella caiguda s'ha d'excloure del càlcul (molts equips defineixen per endavant quins esdeveniments són excepcionals i com es documenten), o mantenir la restricció però acompanyar-la de l'acció que la resol —feina de fiabilitat sobre RDS: Multi-AZ ja n'hi ha, faltarà revisar reintents, temps d'espera i degradació elegant—.
Si producte insisteix amb un motiu legítim (un compromís comercial amb data), la resposta correcta no és saltar-se la política en silenci, sinó fer servir les eines del mòdul: desplegar el codi darrere d'un feature flag apagat, activar-lo per a un negoci, després per al 10 % i només després per a tothom, amb rollback immediat disponible. Això desacobla la data de lliurament del risc, que és precisament per al que es va construir tot això. I l'excepció s'anota: qui la va autoritzar i per què, per revisar-la a la retrospectiva.
Solució 3. Les tres alertes actuals no ho detectarien per un problema de dilució. Un negoci gran pot suposar el 2 % del trànsit total; si totes les seves reserves fallen, l'error rate global puja del 0,1 % al 2,1 %, que probablement supera el llindar de l'1 % d'ApiErrors5xx… o probablement no, si el negoci és més petit o si la fallada només afecta una part de les seves peticions. Amb un negoci del 0,5 % del trànsit, el senyal global és indistingible del soroll, i el mateix passa amb la latència i amb el consum de pressupost.
El disseny que sí que ho detecta: una alerta sobre l'error rate màxim per negoci, no sobre l'agregat. A la pràctica s'implementa emetent una mètrica d'errors agrupada per una dimensió de cardinalitat controlada —no negociId, que serien 340 mètriques i viola la regla de l'apartat 4, sinó una cosa com el segment de mida del negoci, o un comptador de "negocis diferents amb més del 50 % de peticions fallides els últims 5 minuts"—. Aquesta última formulació és la bona: un sol número, cardinalitat u, que salta quan qualsevol negoci està completament trencat encara que l'agregat sigui impecable. Condició: ≥ 1 negoci amb més del 50 % de fallades durant 5 minuts, sobre un mínim de 20 peticions per evitar falsos positius de negocis amb poc trànsit.
Complement imprescindible: quan aquella alerta salti, cal poder respondre "quin negoci?", i això no ho donen les mètriques sinó els logs estructurats amb negociId de l'apartat 2. És la il·lustració perfecta de l'ordre dels tres pilars: la mètrica avisa, el registre explica.
Conclusió
El bucle està tancat. Reservalia ja no desplega a cegues: té mètriques, logs estructurats i traces amb papers diferents —la mètrica avisa, la traça localitza, el registre explica—; vigila els quatre senyals d'or en un panell que cap en una pantalla; ha traduït "està bé?" en dos SLO amb un pressupost d'error de 43 minuts al mes que decideix, amb una taula acordada en fred, quan es desplega amb llibertat i quan toca frenar; marca cada desplegament sobre les gràfiques perquè la primera pregunta d'un incident es respongui en segons; alerta sobre símptomes i no sobre causes, amb tres alertes que desperten i cap més; i alimenta les seves mètriques DORA automàticament des del mateix pipeline, inclosos els desplegaments fallits.
El freeze dels divendres ha desaparegut, i no per valentia sinó pel contrari: perquè ara existeix una regla objectiva que diu quan es pot desplegar i quan no, i perquè un desplegament que es desfà en quatre minuts i es detecta en dos deixa de merèixer una cerimònia. Els números ho avalen: d'1,1 a 12 desplegaments per setmana, de 6,2 dies a 3,5 hores de lead time, de 68 a 9 minuts de recuperació. El change failure rate s'ha quedat al 6,5 % davant de l'objectiu del 5 %, i aquesta és la pista honesta de per on continua la feina.
Perquè les fallades que queden ja no són de desplegament. Són d'un pipeline que comença a engreixar-se i a fer-se lent, de dependències que entren a l'artefacte sense que ningú sàpiga quantes ni de qui són, d'un sistema amb permisos sobre producció que mai no ha passat una revisió de seguretat, i de migracions d'esquema que continuen sent l'únic motiu pel qual el botó de tornada enrere podria no funcionar. El mòdul 4, Pràctiques Avançades de CI/CD, ataca aquests quatre fronts, i comença pel que els ordena tots: la seva primera lliçó, Pipelines de CI/CD, dissecciona l'anatomia completa d'un pipeline —les seves etapes, com s'orquestren, què es paral·lelitza, què es pot saltar i com se'n dissenya un que continuï sent ràpid quan l'equip hagi triplicat la seva mida.
Curs de CI/CD: Integració i Desplegament Continu
Mòdul 1: Introducció al CI/CD
- Conceptes Bàsics de CI/CD
- Beneficis del CI/CD
- Eines Populars de CI/CD
- El Projecte del Curs: l'Aplicació que Automatitzarem
- Mètriques DORA: Com es Mesura el Lliurament de Programari
Mòdul 2: Integració Contínua (CI)
- Introducció a la Integració Contínua
- Configuració d'un Entorn de CI
- Automatització de la Construcció
- Proves Automatitzades
- Qualitat de Codi i Anàlisi Estàtica
- Artefactes, Versionat i Promoció
- Integració amb el Control de Versions
Mòdul 3: Desplegament Continu (CD)
- Introducció al Desplegament Continu
- Automatització del Desplegament
- Infraestructura com a Codi i Entorns Reproduïbles
- Estratègies de Desplegament
- Feature Flags, Rollback i Recuperació davant Errors
- Monitoratge i Retroalimentació
Mòdul 4: Pràctiques Avançades de CI/CD
- Pipelines de CI/CD
- Gestió de Dependències
- Seguretat en CI/CD
- Escalabilitat i Rendiment
- Pipeline as Code: Plantilles, Reutilització i Proves del Pipeline
- Bases de Dades al Pipeline: Migracions Segures
Mòdul 5: Implementació de CI/CD en Projectes Reals
- Cas d'Estudi: Projecte Web
- Cas d'Estudi: Aplicació Mòbil
- Cas d'Estudi: Microserveis
- Cas d'Estudi: Modernitzar un Projecte Legacy
Mòdul 6: Eines i Tecnologies
- Jenkins
- GitLab CI/CD
- CircleCI
- Travis CI
- Docker i Kubernetes
- GitHub Actions a Fons
- Comparativa i Criteris per Triar Eina
Mòdul 7: Exercicis Pràctics
- Exercici 1: Configuració d'un Pipeline Bàsic
- Exercici 2: Integració de Proves Automatitzades
- Exercici 3: Desplegament en un Entorn de Producció
- Exercici 4: Monitoratge i Retroalimentació
- Exercici 5: Enfortir el Pipeline amb Seguretat i Secrets
- Projecte Final: Pipeline Complet d'Extrem a Extrem
