Plantilla de ADR y ejemplos: formatos listos para copiar

La reunión llevaba dos horas. Estábamos debatiendo si usar PostgreSQL o MongoDB para un servicio nuevo. Los argumentos iban y venían: integridad relacional, esquemas flexibles, familiaridad del equipo, complejidad operativa.

Entonces alguien dijo: «¿No tuvimos exactamente esta discusión el año pasado con el servicio de usuarios?»

Silencio. La habíamos tenido. Un año antes habíamos dedicado el mismo tiempo a la misma pregunta y habíamos elegido PostgreSQL. Nadie recordaba el razonamiento, y el ingeniero que había liderado aquella discusión se había ido de la empresa. Así que estábamos teniendo el mismo debate desde cero.

Fue entonces cuando empezamos a escribir Architecture Decision Records. Este artículo es la parte de copiar y pegar: tres plantillas, cuándo usar cada una y tres de nuestras propias decisiones ya rellenadas.

¿Qué es un ADR?

Un architecture decision record es un documento breve que recoge una sola decisión de arquitectura. No un documento de diseño que lo cubre todo sobre un sistema, sino una decisión:

  • Qué decidimos
  • Por qué lo decidimos
  • Qué alternativas consideramos
  • Cuáles son las consecuencias

Un ADR debería caber en una o dos páginas. Si es más largo, probablemente estás documentando más de una decisión. La guía completa cubre cuándo escribir uno, el ciclo de vida y los errores que cometen los equipos; este artículo se limita a los formatos.

La plantilla mínima (Nygard)

Michael Nygard propuso el formato que la mayoría de los equipos todavía usa en un artículo de 2011. Cinco partes: un título que es un sintagma nominal corto, un estado, el contexto («las fuerzas en juego»), la decisión («nuestra respuesta a esas fuerzas») y las consecuencias («el contexto resultante tras aplicar la decisión»). Sus estados son Propuesta, Aceptada, Obsoleta y Sustituida.

# ADR-NNNN: Sintagma nominal corto

## Estado

Propuesta | Aceptada | Obsoleta | Sustituida por ADR-XXXX

## Contexto

¿Qué fuerzas están en juego? Técnicas, organizativas, plazos, presupuesto.
Sé concreto: cifras, restricciones, a quién afecta.

## Decisión

Vamos a ...

## Consecuencias

Qué se vuelve más fácil, qué se vuelve más difícil, qué tenemos que vigilar a partir de ahora.

Nosotros le añadimos una sección: Alternativas consideradas, entre Decisión y Consecuencias. Es la parte que más tiempo ahorra después, porque la pregunta que te hacen un año más tarde rara vez es «¿qué elegimos?» y casi siempre «¿por qué no elegimos X?»

## Alternativas consideradas

### Opción B
- Ventajas: ...
- Inconvenientes: ...
- Por qué se descartó: ...

MADR

MADR (Markdown Architectural Decision Records) es una plantilla más estructurada que se mantiene en adr.github.io/madr. La versión actual es la 4.0.0, publicada el 17 de septiembre de 2024. Pone los metadatos en un frontmatter YAML y convierte las opciones y sus compromisos en secciones explícitas en lugar de prosa.

---
status: propuesta | rechazada | aceptada | obsoleta | sustituida por ADR-XXXX
date: AAAA-MM-DD
decision-makers: ...
consulted: ...
informed: ...
---

# Título corto del problema resuelto y de la solución elegida

## Contexto y planteamiento del problema

Dos o tres frases, o una historia breve. Idealmente formulado como una pregunta.

## Factores de decisión

* Factor 1
* Factor 2

## Opciones consideradas

* Opción A
* Opción B
* Opción C

## Resultado de la decisión

Opción elegida: "Opción A", porque ...

### Consecuencias

* Bueno, porque ...
* Malo, porque ...

### Confirmación

Cómo comprobaremos que la decisión se aplica (revisión, test, fitness function).

## Ventajas e inconvenientes de las opciones

### Opción A

* Bueno, porque ...
* Malo, porque ...

## Más información

Enlaces, decisiones relacionadas, cuándo revisarla.

En MADR, todas las secciones posteriores a Opciones consideradas y Resultado de la decisión son opcionales. Borra las que no uses en lugar de dejar títulos vacíos.

Y-statement

El Y-statement resume una decisión en una sola frase. Procede de Uwe Zdun, Olaf Zimmermann y sus colegas («Sustainable Architectural Design Decisions», IEEE Software, 2013):

En el contexto de <caso de uso o componente>,
ante <preocupación o requisito>,
decidimos <opción>
(y descartamos <otras opciones>),
para lograr <cualidad o beneficio>,
aceptando que <inconveniente>.

Es demasiado corto para contener una sección de contexto completa, y esa es precisamente la idea. Úsalo para decisiones que no merecen una página, como línea de resumen al principio de un ADR más largo o como formato de entrada en un registro de decisiones.

Qué formato usar

Formato Úsalo cuando Cuidado con
Nygard (más alternativas) Estás empezando, o la mayoría de las decisiones tienen un ganador claro y un par de opciones descartadas Secciones de contexto que se convierten en ensayos
MADR Las decisiones son disputadas, varias personas tienen que aprobarlas o quieres que opciones y factores sean comparables entre ADR Rellenar todas las secciones opcionales por costumbre
Y-statement Decisiones pequeñas, un registro de decisiones o un resumen de una línea encima de un ADR más largo Usarlo para decisiones que necesitan una sección de contexto de verdad

Elige uno para el repositorio y mantente fiel a él. Los formatos mezclados son más difíciles de recorrer de lo que es escribir cualquier formato único.

Ejemplo 1: ADR-0042, PostgreSQL para el order service

Esta es la decisión de la historia del principio, en formato Nygard con nuestra sección Alternativas consideradas.

# ADR-0042: Usar PostgreSQL para el Order Service

## Estado

Aceptada

## Contexto

El order service necesita almacenamiento persistente para los datos de
pedidos. Esperamos procesar 50.000 pedidos al día al principio, y
500.000 en dos años. Los pedidos tienen una estructura bien definida,
pero con el tiempo pueden necesitar campos de metadatos adicionales.
El equipo tiene experiencia con bases de datos relacionales y documentales.

## Decisión

Usaremos PostgreSQL 15 como base de datos principal del order service.

Elegimos PostgreSQL porque:

- El cumplimiento ACID es obligatorio para datos financieros de pedidos
- Las columnas JSON aportan flexibilidad de esquema para los metadatos
- Nuestro equipo de infraestructura tiene experiencia operativa con PostgreSQL
- Los patrones de consulta encajan bien con un modelado relacional

## Alternativas consideradas

### MongoDB

- Ventajas: almacenamiento JSON nativo, escalado horizontal más sencillo, evolución flexible del esquema
- Inconvenientes: garantías de consistencia más débiles, el equipo conoce menos su operación,
  requeriría herramientas adicionales para transacciones

### DynamoDB

- Ventajas: totalmente gestionado, operación mínima, escalabilidad excelente
- Inconvenientes: dependencia de AWS, patrones de consulta limitados al acceso por clave
  de partición/ordenación, coste impredecible a gran escala

## Consecuencias

### Positivas

- Fuertes garantías de integridad de los datos
- El equipo puede reutilizar su experiencia con PostgreSQL
- Características operativas bien conocidas

### Negativas

- Las migraciones de esquema requieren más planificación que en una base documental
- El escalado horizontal es más complejo si superamos la capacidad de un solo nodo
- Necesitaremos sharding a nivel de aplicación si llegamos a los límites de escala

### Riesgos

- Puede que haya que revisarla si el volumen de pedidos supera 1M/día
- Las consultas sobre columnas JSON son menos eficientes que en una base documental nativa

## Decisiones relacionadas

- Ver ADR-0007 para saber por qué aceptamos la consistencia eventual
- Sustituye a ADR-0003, que recomendaba MongoDB

Sé concreto en el contexto. «Necesitamos cumplimiento ACID» ayuda mucho más al siguiente lector que «necesitamos fiabilidad». Y sé honesto en las consecuencias: ninguna decisión sale gratis, y escribir los inconvenientes indica a los equipos futuros cuándo toca revisarla.

Ejemplo 2: ADR-0007, comunicación basada en eventos, en MADR

La decisión de Kafka tenía más opciones sobre la mesa y más personas implicadas, que es donde los factores y opciones explícitos de MADR se ganan su espacio.

---
status: aceptada
---

# Usar Kafka para la comunicación asíncrona entre servicios

## Contexto y planteamiento del problema

Nuestros microservicios se comunican de forma síncrona por HTTP. Eso los
acopla fuertemente, y un servicio caído provoca fallos en cascada en
quienes lo llaman. ¿Cómo deberían comunicarse los servicios cuando quien
llama no necesita una respuesta inmediata?

## Factores de decisión

* Resiliencia: la caída de un servicio no debe arrastrar a los demás
* Menor acoplamiento entre servicios

## Opciones consideradas

* Mantener HTTP síncrono
* Comunicación basada en eventos con Apache Kafka

## Resultado de la decisión

Opción elegida: "Comunicación basada en eventos con Apache Kafka", porque
elimina el acoplamiento en tiempo de ejecución que provoca los fallos en cascada.

### Consecuencias

* Bueno, porque los servicios se vuelven más resilientes a los fallos de los demás
* Malo, porque pasamos de consistencia fuerte a consistencia eventual
* Malo, porque ahora operamos un clúster de Kafka
* Malo, porque el equipo necesita formación en patrones basados en eventos

El estado y el título se conservan; los campos date y decision-makers se omiten aquí porque el registro original no los guardó.

Ejemplo 3: ADR-0015, un monorepo de frontend, como Y-statement

La decisión del monorepo cabe en una frase, y esa frase basta para responder a «¿por qué está todo en un solo repositorio?»

En el contexto de nuestras 5 aplicaciones frontend en repositorios separados,
ante los desajustes de versiones y el coste de publicar paquetes para compartir código,
decidimos un único monorepo gestionado con Nx
(y descartamos repositorios separados con mejor gestión de paquetes, así como un monorepo sin Nx),
para lograr compartir código de forma sencilla y un solo pull request que actualice el código compartido y a todos sus consumidores,
aceptando que un repositorio más grande necesita caché de build y que las aplicaciones pueden acoplarse por accidente.

Las opciones descartadas llevan sus motivos en el registro completo: los repositorios separados mantenían el coste de coordinación, y un monorepo sin Nx habría hecho los tiempos de build inasumibles.

Dónde guardarlos

Guarda los ADR en el repositorio que describen, en docs/adr/ o docs/decisions/ (Nygard sugería doc/arch/adr-NNN.md). Se versionan con el código, aparecen en la revisión de código y no se pueden perder en una wiki.

Numéralos de forma secuencial y nunca reutilices un número. Cuando una decisión cambie, escribe un ADR nuevo que sustituya al anterior y actualiza el estado del antiguo, en lugar de reescribir la historia.

El paso que la mayoría de los equipos se salta es conectar un ADR con la parte del sistema a la que afecta. En Archyl, un ADR tiene los campos de Nygard (estado, contexto, decisión, consecuencias) más una fecha y un enlace de «sustituido por», y se vincula a los sistemas, contenedores y componentes a los que dio forma. Quien mire el order service en el diagrama C4 ve ADR-0042 al lado: «¿Por qué este servicio usa PostgreSQL?» está a un clic.

Los errores habituales (escribir los ADR a posteriori, dejar que se extiendan cinco páginas, abandonar la práctica tras el primer trimestre ajetreado) se tratan en la guía completa.

Empieza por uno

¿Aquella reunión de dos horas sobre PostgreSQL contra MongoDB? La siguiente vez que surgió la pregunta, se resolvió en diez minutos, porque alguien encontró ADR-0042. Las restricciones, las alternativas y el razonamiento estaban ahí. Confirmamos que la decisión original seguía siendo válida y seguimos adelante.

Elige una de las plantillas de arriba y pégala en docs/adr/0001-record-architecture-decisions.md. Tu primer ADR puede ser la decisión de escribir ADR.


Más sobre documentación de arquitectura: la guía del modelo C4 | Por qué importa la documentación | Documentar flujos de usuario