StackPractices
beginner Por Mathias Paulenko

Estrategia de Documentación Técnica: Docs as Code

Guía práctica para tratar la documentación como código: versionado, flujos de review, estructura y herramientas que mantienen los docs precisos y mantenibles.

Temas: devops

Introducción

La documentación es una de las actividades de mayor impacto en ingeniería de software. Un sistema bien documentado acorta el onboarding, evita que el mismo incidente se depure dos veces y preserva el contexto cuando un equipo rota. Tratar los docs como código significa aplicar la misma rigurosidad que aplicas al código fuente — control de versiones, code review, verificaciones automatizadas — a las palabras que describen cómo funciona el sistema.

Esta guía es para engineering leads, platform teams y desarrolladores senior que mantienen un servicio o una plataforma y quieren un sistema de documentación que no se pudra. Cubre los cuatro documentos que necesita cada servicio, el flujo de trabajo docs-as-code, las herramientas que lo hacen práctico y las métricas que te dicen si el sistema funciona. No cubre la generación de referencia de API en profundidad — eso es un tema aparte que maneja el tooling de OpenAPI.

Cuándo usar Docs as Code

Adopta docs as code cuando al menos una de estas condiciones sea cierta:

  • Más de un equipo toca el mismo servicio. Un solo autor puede mantener una wiki en su cabeza; dos equipos no. El historial de Git y el review hacen visibles los desacuerdos.
  • El onboarding tarda más de un día. Si las incorporaciones pasan una semana preguntando “¿dónde está el runbook?”, el sistema de documentación es el cuello de botella.
  • Los incidentes se repiten con la misma causa raíz. Un runbook que vive junto al código se actualiza en el mismo PR que arregla el bug; un runbook en una wiki separada no.
  • Despliegas varias veces por semana. Los deploys rápidos hacen que los docs se desactualicen rápido; acoplar las actualizaciones de docs a los cambios de código es la única forma realista de mantenerlos al día.
  • Necesitas demostrar compliance o traza de auditoría. Los entornos regulados (SOC 2, ISO 27001, HIPAA) se benefician de documentación versionada, revisada y con un owner claro.

No adoptes el sistema completo cuando:

  • El proyecto es un prototipo de un solo mantenedor sin consumidores externos. Un README basta; el overhead de ADRs y runbooks te frenará.
  • El equipo no tiene pipeline de CI ni planes de añadirlo. Docs-as-code sin chequeo automatizado de links y linting se pudre igual de rápido que una wiki.
  • La propiedad de la documentación no está clara. Si nadie responde por los docs, el flujo no lo arreglará — solo moverá el cementerio de Confluence a Git.

Los Cuatro Documentos Esenciales

Cada sistema debería tener estos cuatro docs. Responden preguntas diferentes a profundidades diferentes, y tienen ciclos de vida distintos — por eso una sola carpeta de “documentación” rara vez funciona.

DocumentoRespondeAudienciaFrecuencia de actualización
README¿Qué es esto? ¿Cómo lo ejecuto?Desarrolladores nuevos, usuariosCada cambio mayor
Architecture Decision Record (ADR)¿Por qué elegimos esto?Mantenedores actuales y futurosUna vez por decisión mayor
Runbook¿Cómo lo arreglo cuando se rompe?Ingenieros on-callDespués de cada incidente
Referencia de API¿Qué hace este endpoint?Consumidores de APIAuto-generada desde el código

El README cambia con el código. El ADR es append-only — lo escribes una vez y solo actualizas el estado. El runbook cambia después de cada incidente, no en un calendario. La referencia de API nunca debería escribirse a mano; si lo está, ya está mal.

Flujo de Trabajo Docs as Code

El flujo es el mismo que un cambio de código, con una pasada extra de review por precisión.

Flujo docs-as-code — el autor escribe docs en Markdown, abre un PR, el revisor revisa código y docs, CI ejecuta lint/links/spelling, el merge publica los docs automáticamente

La propiedad clave es que el cambio de documentación y el cambio de código viven en el mismo pull request. Si se dividen en dos repos o dos PRs, uno se desplegará sin el otro.

Por Qué Funciona

PrincipioCómo se aplica en Docs as Code
Control de versionesEl historial de Git muestra cuándo cambiaron los docs y por qué — git blame sobre un párrafo es más honesto que una fecha de “última revisión”.
Code reviewLos reviews capturan inexactitudes técnicas, no solo typos. Un revisor que entiende el código puede rechazar un doc que lo contradice.
AutomatizaciónCI captura links rotos, anclas obsoletas y drift de formato antes de que lleguen a producción.
BranchingLos cambios de docs se despliegan con el código que describen, así una feature branch es autocontenida.

Estructura del README

Un README debería responder estas preguntas en orden:

# Nombre del Servicio

Descripción de una línea de qué hace este servicio.

## Quick Start

Cómo ejecutarlo localmente en menos de 5 minutos.

## Visión General de Arquitectura

Diagrama de alto nivel y dependencias clave.

## Configuración

Variables de entorno requeridas con ejemplos.

## Testing

Cómo ejecutar tests unitarios, de integración y E2E.

## Deployment

Cómo se despliega este servicio (link a CI/CD, lista de ambientes).

## Troubleshooting

Errores comunes y cómo resolverlos.

## Contributing

Link a guías de contribución y código de conducta.

Architecture Decision Records (ADRs)

Los ADRs capturan el contexto y las consecuencias de decisiones técnicas mayores. Evitan debates futuros sobre “¿por qué lo hicimos así?”

Plantilla de ADR

# ADR-042: Adoptar Kafka para Event Streaming

## Estado
Aceptado

## Contexto
El servicio de órdenes necesita publicar eventos a 4 consumidores downstream. Los callbacks REST son poco fiables y crean acoplamiento fuerte.

## Decisión
Adoptar Apache Kafka como la plataforma de event streaming.

## Consecuencias

### Positivas
- Desacopla productores de consumidores
- Soporta replay para nuevos consumidores y debugging
- Maneja backpressure vía consumer lag

### Negativas
- Complejidad operativa (ZooKeeper, brokers, particiones). Ver [arquitectura event-driven](/guides/event-driven-architecture-guide/).
- El equipo necesita aprender [patrones event-driven](/guides/event-driven-architecture-guide/)
- La consistencia eventual requiere el patrón Saga para algunos flujos

Regla general: escribe un ADR para cualquier decisión que cueste más de 2 semanas revertir.

Runbooks

Un runbook es una guía paso a paso para responder a una alerta conocida o modo de fallo.

Buena Estructura de Runbook

# Runbook: Pool de Conexiones de Base de Datos Agotado

## Síntomas
- Alerta: `db_pool_connections_exhausted`
- Impacto al usuario: las requests de la API hacen timeout después de 5 segundos

## Diagnóstico
1. Verificar uso actual del pool: `SELECT count(*) FROM pg_stat_activity;`
2. Identificar queries lentas: `SELECT * FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10;`
3. Revisar logs de aplicación por leaks de conexión

## Resolución
1. Si es una query lenta: matar la query, [agregar índice](/recipes/database-indexing/), o escalar [réplicas de lectura](/guides/database-design-guide/)
2. Si es un leak de conexión: reiniciar los pods de la app (temporal), luego desplegar el fix
3. Si persiste: aumentar el tamaño del pool en config y redesplegar

## Escalación
Si la resolución falla después de 15 minutos, escalar al equipo de Base de Datos on-call.

Herramientas de Documentación

El stack de herramientas importa menos que el flujo, pero el stack equivocado añade fricción. Elige herramientas que encajen con el tipo de doc, no una herramienta para todo.

HerramientaMejor paraProsContras
Markdown en GitREADMEs, ADRs, runbooksUniversal, versionado, gratis, revisableSin búsqueda integrada; la aportas tú
MkDocs MaterialDocs de ingeniería internosRápido, basado en Python, buena búsqueda, versionadoTheming limitado frente a Docusaurus
DocusaurusDocs de producto con componentes ReactTheming rico, versionado, ecosistema de pluginsBuild más pesado, solo Node
BackstageCatálogo de servicios + portal de docsCentraliza ownership de servicios, pluginsSetup significativo; excesivo para menos de 20 servicios
Notion / ConfluenceConocimiento cross-team, docs de procesoWYSIWYG, fácil para no ingenierosSin historial de git; el ownership se pudre en silencio
Swagger / OpenAPIReferencia de APIAuto-generada desde el código, siempre en sincroníaLimitada a la superficie de API; sin narrativa
Mermaid / PlantUMLDiagramas as codeVersionados, diffables, revisables en PRsCurva de aprendizaje; los diagramas complejos se vuelven verbosos

Cómo Elegir el Stack Correcto

Un error común es elegir una herramienta para los cuatro tipos de doc. El stack que funciona para un README (Markdown en el repo) es incorrecto para una guía de onboarding cross-team (Notion), y la herramienta que funciona para referencia de API (OpenAPI) es incorrecta para explicación de arquitectura (Markdown largo con diagramas Mermaid).

Una división pragmática para una plataforma de tamaño medio:

  • Docs adyacentes al código (README, ADR, runbook): Markdown en el repo del servicio. Sin excepciones. Estos docs cambian con el código y necesitan el mismo rastro de review.
  • Catálogo de servicios y discovery: Backstage si tienes más de 20 servicios; si no, un índice OWNERS.md único en el monorepo basta.
  • Referencia de API: OpenAPI spec commiteada en el repo, renderizada por el sitio de docs. Nunca escrita a mano.
  • Conocimiento cross-team (flujos de onboarding, procesos de RRHH, runbooks de plataformas compartidas): Notion o Confluence, con un owner nombrado por página y un job trimestral de stale-review.
  • Diagramas: Mermaid para flowcharts y diagramas de secuencia, PlantUML para topologías de deployment. Ambos renderizan a SVG en build time y se mantienen diffables.

La prueba para cualquier herramienta del stack: si una incorporación nueva no encuentra el doc que necesita en menos de cinco minutos, la herramienta es la elección equivocada, por muy bueno que sea el contenido.

Métricas de Documentación

Un sistema de docs-as-code sin métricas es una wiki con pasos extra. Mide un conjunto pequeño de indicadores leading y lagging para saber si el sistema funciona.

MétricaTipoObjetivoCómo medirla
% servicios con READMECobertura100%Script que recorre el catálogo de servicios y comprueba README.md
% servicios con runbookCobertura100%El mismo script, comprueba runbook.md o una entrada de runbook en el catálogo
Docs actualizados en el mismo PR que el códigoFrescura> 90%Heurística de diff: los PRs que tocan src/ deberían tocar también docs/ o *.md
Tiempo de onboarding al primer PROutcome< 1 díaAuto-reportado por las incorporaciones en un check-in a las 2 semanas
Búsquedas sin resultadoDiscoverability< 10%Analítica de búsqueda de MkDocs/Docusaurus/Backstage
ADRs por servicio por trimestreVelocidad de decisiones1-3Conteo de ficheros añadidos bajo adr/
Runbooks disparados y resueltos sin escalaciónCalidad del runbookCrecientePost-incident review del on-call

Evita métricas de vanidad como “conteo total de palabras” o “número de páginas”. Suben para siempre y no te dicen nada. Las dos que más importan son el tiempo de onboarding y las búsquedas sin resultado — ambas miden si un lector nuevo encuentra lo que necesita.

Lo que Funciona

  • Escribe el README primero — si no puedes explicar cómo ejecutar el servicio, el servicio no está listo para desplegar.
  • Mantén los docs junto al código — los docs en un repo separado se pudren más rápido que el código que describen.
  • Automatiza el chequeo de links en CI — los links rotos destruyen confianza; CI debería fallar el build por ellos, no solo avisar.
  • Usa diagramas as code — Mermaid y PlantUML mantienen los diagramas versionados, revisables y diffables.
  • Revisa docs en PRs — un cambio de código sin cambio de doc es un PR incompleto; conviértelo en un merge check.
  • Establece una política de frescura — marca los docs no actualizados en 12 meses para revisión, y borra los que nadie posee.

Errores Comunes

  • Escribir docs solo para principiantes. Los expertos también necesitan docs — las referencias de API, las vistas de arquitectura y los ADRs son donde los ingenieros senior pasan de verdad su tiempo de lectura.
  • Crear un cementerio de wiki. Las wikis se desactualizan porque no hay proceso de review ni owner. Si no puedes nombrar al owner de una página, la página ya está muerta.
  • Documentar el qué, no el por qué. El “qué” está en el código. El “por qué” — por qué Kafka y no RabbitMQ, por qué Postgres y no MySQL — es lo que olvidas en seis meses y lo que un ADR existe para preservar.
  • Sobre-documentar. Si el código es autoexplicativo, no lo repitas en prosa; explica la intención y las restricciones que el código no muestra.
  • Separar docs y código en repos distintos. La fricción del cambio de contexto garantiza que los docs no se actualizarán. Un repo, un PR, un review.

Modelo de Ownership de Documentación

Un flujo de docs-as-code maneja la mecánica — versionado, review, publicación. No resuelve el ownership. Sin owner, todo doc termina huérfano, y los docs huérfanos se pudren.

El enfoque CODEOWNERS

Toma prestado el patrón del code review: un fichero CODEOWNERS en cada repo declara quién es responsable de qué rutas. Aplica la misma idea a los docs.

# .github/CODEOWNERS

# README y docs de arquitectura son del equipo del servicio
/README.md                    @payment-team
/architecture.md              @payment-team

# Los runbooks son de la rotación on-call
/runbook.md                   @payment-oncall

# Los ADRs son del tech lead
/adr/                         @payment-tech-lead

Esto te da tres propiedades:

  • Un PR que toca runbook.md solicita automáticamente review de la rotación on-call, no de todo el equipo.
  • Un job de stale-docs puede etiquetar a los owners directamente en vez de abrir un issue genérico.
  • Cuando un equipo se reorganiza, el fichero CODEOWNERS es el único sitio donde actualizar el ownership.

Qué hacer con los docs huérfanos

Cada trimestre, ejecuta un script que liste los ficheros markdown no tocados en 12 meses. Para cada uno:

  1. Si tiene owner en CODEOWNERS, abre un issue pidiendo al owner que lo revise o lo borre.
  2. Si no tiene owner, publícalo en el canal del equipo y da al equipo dos semanas para reclamarlo.
  3. Si nadie lo reclama, bórralo. Un doc sin owner es peor que ningún doc — parece autoritario y está mal.

Borrar docs parece destructivo, pero es la acción de mantenimiento de mayor impacto que puedes tomar. Un doc borrado deja de engañar a los lectores; un doc sin owner sigue engañándolos hasta que alguien abre un bug que nadie recoge.

Temas Avanzados

Escenario: Sistema de Documentación para una Plataforma

El framework Diataxis separa la documentación en cuatro tipos por propósito, no por tema. Es la estructura que mejor escala para una plataforma con muchos equipos.

TipoPropósitoAudienciaEjemplo
TutorialAprenderNovatos”Crea tu primer servicio”
GuíaResolverPracticantes”Cómo configurar Redis”
ReferenciaConsultarTodosAPI docs, flags de CLI
ExplicaciónEntenderCuriosos”Por qué usamos Kafka”

Un catálogo de servicios de Backstage mapea cada servicio a sus docs por tipo:

services/
  payment-service/
    README.md          # Guía: cómo ejecutar en local
    api.yaml           # Referencia: OpenAPI spec
    runbook.md         # Guía: qué hacer cuando falla
    architecture.md    # Explicación: decisiones de diseño
    on-call.md         # Guía: procedimientos de on-call
  order-service/
    ...

tutorials/
  new-microservice.md  # Tutorial: paso a paso
  new-endpoint.md
  local-dev-setup.md

adr/
  001-record-events.md
  002-use-postgresql.md
  003-adopt-kafka.md

Un runbook en esta estructura es un doc de guía indexado por síntoma, no por componente:

# Runbook: Payment Service

## Síntoma: Tasa de error > 1%
1. Revisa el dashboard de errores para el endpoint que más falla.
2. Revisa el último deploy: `kubectl rollout history deployment/payment`.
3. Si hubo deploy en los últimos 30 minutos, haz rollback.
4. Si no, revisa los logs en Loki: `{service="payment"} |= "error"`.
5. Revisa la base de datos: conexiones activas, queries largas, locks.
6. Si la base de datos está saturada, escala al DBA on-call.
7. Abre un post-mortem en 48 horas sea cual sea el resultado.

## Síntoma: Latencia p99 > 500ms
1. Abre el trace en Jaeger y encuentra el span más lento.
2. Si el span lento es una query de base de datos, ejecuta `EXPLAIN ANALYZE` sobre ella.
3. Si el span lento es una llamada a API externa, revisa la status page del proveedor.
4. Si el span lento es CPU-bound, revisa si HPA está escalando y por qué.
5. Abre un post-mortem si el incidente duró más de 10 minutos.

Las lecciones de plataformas que han hecho esto a escala:

  • Diataxis separa los tipos de doc por propósito, así un lector sabe si está aprendiendo, resolviendo, consultando o entendiendo — y el doc está escrito para esa intención.
  • Los runbooks son docs vivos: actualízalos después de cada incidente, no en un calendario trimestral. Un runbook que no se tocó en el último incidente probablemente está mal.
  • Los ADRs preservan el “por qué” de las decisiones; sin ellos, el equipo rediscute el mismo argumento cada seis meses.
  • Backstage centraliza el catálogo de servicios y enlaza cada servicio con sus docs, así el discovery no es “pregunta a alguien en Slack”.
  • Mide la calidad de los docs como mides la del código — con métricas, owners y review.

Preguntas frecuentes

¿Quién debería escribir la documentación?

El ingeniero que construyó el cambio. Tiene el contexto que un escritor técnico no puede reconstruir después. Los escritores técnicos pueden pulir estructura, tono y consistencia, pero la fuente de verdad debe venir del implementador. Haz que escribir docs sea parte del Definition of Done para que se despliegue con el código, no después.

¿Cómo evito que los docs se desactualicen?

Trata los docs desactualizados como un bug, no como una tarea. Añade una etiqueta documentation a tu bug tracker y priorízala junto a los bugs de código. Requiere actualizaciones de README en el mismo PR que los cambios de código — un check de CI que falle cuando src/ cambia pero ningún *.md cambia es la aplicación más barata. Ejecuta un job de stale-docs que marque cualquier fichero markdown sin tocar en 12 meses y se lo asigne a su owner para revisión.

¿Deberíamos usar Confluence o Markdown en Git?

Usa ambos para propósitos distintos. Markdown en Git para docs adyacentes al código (READMEs, ADRs, runbooks) que cambian con el código y necesitan rastro de review. Confluence o Notion para conocimiento cross-team, onboarding y docs de proceso que evolucionan al margen de cualquier repo. El modo de fallo es mezclarlos: poner runbooks en Confluence donde el ingeniero on-call no los encuentra a las 3 a.m., o poner flujos de onboarding de RRHH en Git donde los no ingenieros no pueden editarlos.

¿Cómo versiono la documentación con los releases?

Etiqueta los docs con la misma versión que el código. En un monorepo, mantén una carpeta docs/ por versión major o usa un campo version en el frontmatter que el sitio de docs usa para construir selectores versionados. En polyrepo, ramifica los docs junto al código — una rama release/2.x publica docs/2.x. Nunca mantengas un único sitio de docs "current" para software con varias versiones soportadas en producción; los usuarios en 2.x seguirán las instrucciones de 3.x y romperán su setup.

¿Qué pertenece a un ADR y qué no?

Un ADR registra el contexto, la decisión y las consecuencias de una elección técnica significativa. No registra detalles de implementación, instrucciones paso a paso ni opiniones sin consecuencias. Una buena prueba: si la decisión se revirtiera, ¿un mantenedor futuro necesitaría entender por qué se tomó? Si sí, escribe un ADR. Si la respuesta es "pueden leer el código", sáltalo. Usa la plantilla de ADR como punto de partida.

¿Cómo mido si la documentación es realmente útil?

Mide el tiempo de onboarding (pregunta a las incorporaciones cuánto tardaron en hacer su primer PR) y la tasa de búsquedas sin resultado (lo que la gente buscó y no encontró). Ambas miden si un lector encuentra lo que necesita, que es el único outcome que importa. Evita métricas de vanidad como conteo total de palabras o page views — suben para siempre y no te dicen nada sobre la calidad.