Tu CFO no necesita entender el acoplamiento ni la cobertura de tests para tomar una buena decisión sobre la deuda técnica. Necesita tres números: cuánto cuesta la deuda por trimestre, cuánto cuesta arreglarla y cómo sabrás que el arreglo ha funcionado. La mayoría de los equipos de ingeniería nunca produce esos números, así que la petición llega como "necesitamos un sprint de refactorización" y pierde frente a la siguiente funcionalidad del roadmap.
Ya tienes los datos: el historial de git, los registros de los pipelines de CI y las revisiones de incidentes. Esta guía los convierte en un modelo de costes que finanzas puede comprobar, un registro que lo mantiene al día y un caso de una página para pagar la deuda.
Qué cuenta como deuda y qué no
La deuda técnica es un atajo en el código que hace que el trabajo futuro sea más lento o más arriesgado. Como un préstamo, tiene dos partes:
- El principal es lo que costaría arreglar el atajo ahora: las semanas-ingeniero para sustituir las reglas escritas a fuego en el código, añadir los tests que faltan o dividir el módulo.
- Los intereses son lo que pagas cada mes que no lo haces: las horas extra en cada cambio, los incidentes, las funcionalidades que salen tarde.
Llega de dos maneras. La deuda deliberada es una concesión hecha a propósito y puesta por escrito: "dejamos el IVA fijo en el código solo para Portugal para lanzar en marzo; lo revisamos antes de vender en España". La degradación accidental no es decisión de nadie: dependencias que se dejan envejecer, un módulo que creció sin dueño, un diseño pensado para una décima parte del tráfico actual. Las dos cuestan dinero, pero la degradación es la que sorprende a los presupuestos, porque nadie la registró.
Muchas de las cosas de las que se quejan los ingenieros no son deuda en este sentido:
- Código feo que nadie toca. Si un archivo no ha cambiado en dos años, no cobra intereses. Déjalo en paz.
- Funcionalidades que faltan. Lo que el producto todavía no hace es roadmap, no deuda.
- Bugs. Un defecto solo se convierte en señal de deuda cuando la misma zona no deja de producirlos.
- Tecnología antigua que sigue teniendo soporte y sigue encajando. La edad, por sí sola, no cuesta nada.
La regla de la que depende el resto de esta guía: solo se pagan intereses donde el código sigue cambiando. Tu deuda más cara no es tu peor código. Está en los archivos que tu equipo edita cada semana.
Un modelo de costes que un CFO acepta
Finanzas acepta un modelo cuyos datos de entrada se pueden rastrear hasta una fuente. Usa tres líneas: fricción, incidentes y retraso. Todos los números que siguen son un ejemplo: sustituye cada uno por los tuyos.
Empieza por el coste empresa por hora de un ingeniero: salario más cotizaciones a cargo de la empresa, equipo, licencias y oficina, dividido entre las horas realmente disponibles para trabajar después de vacaciones y reuniones. Finanzas puede darte esta cifra. Pongamos que son 75 €.
Fricción. Un equipo de 8 ingenieros pierde 4 horas cada uno por semana por culpa de un único elemento de deuda: esperar builds lentos, pasadas de regresión manuales, rodear un módulo que nadie se atreve a tocar. En un trimestre de 12 semanas laborables: 8 × 4 × 12 × 75 € = 28.800 €.
Incidentes. Cuenta solo los incidentes cuya revisión señala ese elemento de deuda como causa. Pongamos que hubo 3 este trimestre. Cada uno costó 12 horas-ingeniero (900 €) y tuvo 1.600 € de impacto directo en el negocio según tus propios registros: reembolsos, créditos de servicio, pedidos perdidos durante la caída. Son 3 × 2.500 € = 7.500 €. Deja las horas de incidentes fuera de la línea de fricción para no contar ninguna hora dos veces.
Retraso. Una funcionalidad cuyo business case prometía 6.000 € al mes de margen bruto salió con un mes de retraso, y el equipo puede demostrar que el retraso vino del elemento de deuda. Son 6.000 €. Usa la cifra del business case original, no una estimación nueva hecha para este argumento.
Intereses del trimestre: 28.800 € + 7.500 € + 6.000 € = 42.300 €, unos 14.100 € al mes.
Ahora el principal. Arreglar el elemento requiere 2 ingenieros durante 6 semanas: 12 semanas-ingeniero × 35 horas × 75 € = 31.500 €.
Reclama solo la reducción que vas a medir. Pongamos que el arreglo reduce la fricción a la mitad y acaba con los incidentes: 14.400 € + 7.500 € = 21.900 € al trimestre, o 7.300 € al mes. El periodo de retorno es 31.500 € ÷ 7.300 €, algo más de cuatro meses. Deja el retraso fuera del retorno, porque los retrasos pasados no vuelven.
Rellena esto con tus propias cifras:
Friction = engineers x hours lost per week x working weeks x loaded hourly cost
Incidents = incidents linked to the item x (engineer hours x hourly cost + business impact)
Delay = months of delay x monthly value from the feature's own business case
Interest per quarter = Friction + Incidents + Delay
Principal = engineer-weeks to fix x available hours per week x loaded hourly cost
Payback in months = Principal / (interest per month the fix will remove)De dónde salen los números
Cada dato de entrada sale de sistemas que ya usas.
Hotspots de cambio desde git
Esto cuenta cuántos commits tocaron cada archivo durante el último año:
git log --since="12 months ago" --format= --name-only | grep -v '^$' | sort | uniq -c | sort -rn | head -20Ignora los lockfiles y el código generado; el resto muestra dónde pasa el tiempo tu equipo. Cambiar mucho no es deuda por sí solo, así que añade dos señales: cuántos de esos commits fueron correcciones de bugs y qué tamaño tiene el archivo.
cd "$(git rev-parse --show-toplevel)" || exit 1
since="12 months ago"
git log --since="$since" --format= --name-only | grep -v '^$' | sort | uniq -c | sort -rn | head -20 |
while read -r changes file; do
[ -f "$file" ] || continue
fixes=$(git log --since="$since" -i -E --grep='fix|bug' --format=%h -- "$file" | wc -l)
lines=$(wc -l < "$file")
printf '%7s %5s %7s %s\n' "$changes" "$fixes" "$lines" "$file"
doneLas columnas son cambios, commits de corrección, líneas y ruta. Un archivo grande que cambia cada semana y no deja de necesitar correcciones está cobrando intereses. Un archivo grande que nunca cambia, no. Si tienes un analizador de complejidad, su puntuación es mejor indicador que el número de líneas.
Conoce los límites del recuento de correcciones. Depende de la disciplina en los mensajes de commit. El patrón también coincide con "prefix", "debug" y "fixture". Los squash merges reducen muchos commits a uno, y -- "$file" no sigue los renombrados. Si tu equipo usa conventional commits, --grep='^fix' es más preciso. Trata el número como un ranking, no como una medición.
Para convertir hotspots en horas, compara los tiempos de ciclo de los tickets: si los cambios en el módulo de precios tardan una mediana de seis días y los cambios comparables en otras partes tardan dos, la diferencia es fricción que puedes contar.
Duración de CI
Exporta la duración de los pipelines de la rama principal del último año y representa la mediana semanal. Ponle precio a la espera: si la mediana pasó de 8 a 20 minutos, tu equipo lanza 30 pipelines al día que alguien espera, y supones que la mitad de cada espera se pierde en el cambio de contexto, son 30 × 12 × 0,5 = 180 minutos al día. Son 15 horas a la semana, casi 2 de las 4 horas por ingeniero del ejemplo. La espera de CI es un dato de entrada de la fricción, no un coste aparte.
Tasa de fallos en cambios y lead time
La tasa de fallos en cambios es la proporción de despliegues a producción que necesitaron un rollback, un revert o un hotfix. Tu historial de despliegues da el denominador. Para una cota inferior del numerador, cuenta los reverts:
git log main --since="3 months ago" --oneline --grep='^Revert "' | wc -lEl recuento no incluye los rollbacks hechos volviendo a desplegar una versión anterior ni las correcciones publicadas como commits nuevos. El lead time es el tiempo que va del merge a producción, y lo registran tus jobs de deploy de CI. Divide las dos métricas por zona: si los cambios en archivos hotspot fallan o esperan más que el resto, esa diferencia son intereses.
Tiempo de onboarding
Apunta la fecha de incorporación de cada ingeniero nuevo y busca su primer commit:
git log --reverse --author="new.joiner@example.com" --format='%ad' --date=short | head -1Haz el seguimiento por persona, junto con el tiempo que tarda en cambiar un archivo hotspot sin pairing. Si no deja de crecer, vuelves a pagarlo con cada contratación.
Consigue estos números para tu propio código. Solicita una evaluación gratuita de deuda técnica: ejecutamos el análisis de hotspots y de frecuencia de correcciones en tus repositorios, revisamos la tendencia de duración de tu CI y tu tasa de fallos en cambios, y ponemos precio a tus principales elementos de deuda con tu propio coste empresa por hora.
Mantén un registro de deuda
Los números se quedan obsoletos si no viven en algún sitio. Cada entrada necesita: dónde está, un síntoma que cualquiera pueda observar, los intereses al mes con su evidencia, un principal estimado, un responsable y una decisión.
- id: TD-021
where: services/orders/erp-sync/
type: accidental # or: deliberate
recorded: 2026-09-14
symptom: >
Every change to the order export needs a manual end-to-end check;
2 of the last 6 incidents started here.
interest_per_month:
hours: 30
eur: 2250
evidence: hotspot report, incident reviews, ticket cycle time
principal_estimate:
engineer_weeks: 4-6
owner: orders-lead
decision: add contract tests now, then replace the sync job in stages
review: 2026-12-01Para mantenerlo vivo:
- Tenlo junto al código, como archivo en el repositorio o como issues etiquetadas, donde los ingenieros ya trabajan.
- Haz que la deuda deliberada pague su entrada. Un atajo tomado a propósito necesita una entrada con responsable y fecha de revisión antes del merge.
- Revísalo cada mes durante treinta minutos. Vuelve a ejecutar el script de hotspots, actualiza los intereses de las primeras entradas y asigna un responsable a cada entrada que no lo tenga, o ciérrala.
- Registra el resultado. Cuando pagues un elemento, anota el efecto medido junto a la estimación. Ese historial es lo que consigue que se apruebe la siguiente propuesta.
Pagar la deuda
Una parte fija de la capacidad
Reserva una parte de cada iteración para elementos del registro e impide que sea lo primero que se recorta. Dimensiónala a partir de tus propios intereses: si la fricción le cuesta a cada ingeniero 4 de 35 horas a la semana, una parte de entre el 10 y el 15 por ciento significa que dedicas al principal más o menos lo que ya pierdes en intereses.
Paga en los hotspots que ya estás cambiando
Cuando un ticket toca uno de los veinte primeros hotspots, su estimación incluye limpiar esa zona. El contexto ya está cargado y los tests se ejecutan de todos modos, así que es la forma más barata de pagar deuda, y cae justo donde están los intereses.
Estrangula las grandes reescrituras
Para un módulo demasiado grande para arreglarlo de una vez, pon una fachada delante y mueve a la nueva implementación una ruta, una capacidad o un segmento de clientes cada vez. Cada paso llega a producción y se puede medir, y el código antiguo se reduce hasta que se puede borrar. Así es como una migración por etapas de monolito a microservicios evita la reescritura de golpe, el proyecto con más varianza que le puedes presentar a un CFO.
Frena la deuda nueva en la revisión
Pagar deuda no sirve de nada si entra deuda nueva al mismo ritmo. Pon las reglas en CI para que no dependan del humor de quien revisa: tests obligatorios para el código modificado, actualizaciones de dependencias con calendario y ningún TODO anónimo. Esta comprobación hace fallar una merge request que añada un TODO o un FIXME sin ID de ticket (haz antes un fetch de la rama de destino en el job):
diff=$(git diff origin/main...HEAD -U0) || exit 1
if printf '%s\n' "$diff" | grep -E '^\+' | grep -v '^+++' | grep -E 'TODO|FIXME' | grep -vE '(TODO|FIXME)\([A-Z]+-[0-9]+\)'; then
echo "TODO/FIXME without a ticket ID, write it as TODO(PAY-123)"
exit 1
fiLos hábitos de revisión que impiden que la deuda se forme están en nuestras reglas de clean code para equipos en producción.
Presentarlo en una página
Lleva a finanzas una página por propuesta, en este orden:
- 1Coste por trimestre. Las tres líneas, cada una con su fuente: informe de hotspots, revisiones de incidentes, el business case de la funcionalidad.
- 2Riesgo. Lo que empeora si nada cambia: la tendencia de incidentes en esa zona, un runtime que se acerca al fin de soporte, conocimiento que solo tiene una persona.
- 3La propuesta. El principal como rango, personas y duración, qué se aplaza para financiarlo y el punto en el que paras si los números no se mueven.
- 4Cómo vas a medir el efecto. La línea base de hoy y las mismas medidas a los 30, 60 y 90 días: horas perdidas, incidentes en la zona, lead time, duración de CI.
- 5La decisión que necesitas. Una frase.
Lo que no debes decir ante un público de finanzas:
- "El código es un desastre" o "tenemos que refactorizar". Eso describe tu frustración, no un coste.
- Story points y velocidad. Son unidades internas que finanzas no puede auditar.
- "Ahorro". A los ingenieros se les paga igual. Di "capacidad devuelta al roadmap", salvo que el plan de contratación cambie de verdad.
- Medias del sector. Los números de otros provocan preguntas que no puedes responder. Tus propios datos las aguantan.
- Una única cifra precisa. Da un rango y explica los supuestos.
Empieza por un elemento
No le pongas precio a todo el código. Toma la primera entrada del informe de hotspots, pásala por el modelo con tu propio coste empresa por hora y lleva una página a tu próxima conversación de presupuesto. Si estás planificando nuevo desarrollo web sobre un código que ya arrastra esta deuda, ponle precio a la deuda antes de que el trabajo nuevo caiga encima.
Reserva una evaluación gratuita de deuda técnica y ejecutaremos el análisis en tus repositorios, crearemos contigo las primeras entradas del registro y redactaremos el caso de una página para tu elemento principal, listo para tu CFO.