Son las 16:42 de un viernes.
Alguien abre un módulo que lleva ocho años en producción y pronuncia una frase que suele salir cara:
«Esto habría que reescribirlo entero».
El código no es bonito. Hay nombres mejorables, alguna función demasiado larga, una dependencia que ya ha cumplido años y comentarios que probablemente fueron escritos para otra civilización.
Pero hay un pequeño detalle.
Ese módulo funciona.
Cambia dos veces al año. Apenas genera incidencias. Y cuando cambia, el equipo sabe perfectamente dónde tocar.
A tres carpetas de distancia hay otro módulo bastante más moderno. Tiene mejor aspecto, patrones reconocibles y nombres que pasarían una revisión de código sin levantar sospechas.
También se modifica cada semana, rompe cosas con demasiada facilidad y obliga a probar manualmente media aplicación antes de desplegar.
¿Cuál tiene más deuda técnica?
La respuesta útil no sale de contar code smells.
Sale de entender cuál de los dos está frenando más al sistema.
La deuda técnica suele tratarse como una lista de defectos que debemos eliminar. Cuanto más limpia quede la lista, mejor ingeniería estamos haciendo.
No funciona así.
No toda la deuda técnica debe pagarse. Pero toda la deuda relevante debería entenderse, priorizarse y gestionarse conscientemente.
Priorizar deuda técnica no consiste en limpiar el repositorio hasta dejarlo perfecto. Consiste en decidir dónde una intervención reduce de verdad el coste, la fricción o el riesgo.
El código feo no es el problema
La deuda técnica no se prioriza por lo antiguo o desagradable que parezca el código. Se prioriza por los intereses que estamos pagando: fricción, riesgo, tiempo, incidencias y dificultad para evolucionar.

La deuda técnica no es una puntuación de calidad
Una aplicación que lleva años en producción acumula historia.
Decisiones tomadas con la información disponible en aquel momento. Librerías que envejecen. Integraciones que se vuelven críticas. Atajos que iban a durar dos semanas y siguen ahí tres años después. Procesos manuales que nadie automatizó porque siempre había algo más urgente.
Eso no convierte automáticamente el sistema en un desastre.
De hecho, cierta deuda es inevitable cuando un producto evoluciona.
El error aparece cuando confundimos tres cosas distintas:
- código que hoy escribiríamos de otra manera;
- deuda que genera fricción;
- deuda que genera un riesgo importante.
No tienen la misma prioridad.
Un nombre de variable mediocre en un módulo congelado puede molestarnos cada vez que lo vemos.
Una librería sin soporte que procesa datos sensibles quizá no moleste a nadie durante meses.
Solo una de las dos debería quitarnos el sueño.
Por eso la pregunta «¿cuánta deuda técnica tenemos?» suele ser menos interesante que otra:
¿Dónde estamos pagando intereses por esa deuda?
Los intereses pueden aparecer como tiempo, incidencias, incertidumbre, riesgo, dependencia de personas o dificultad para evolucionar el producto. Ahí empieza una conversación mucho más útil.
La metáfora no es solo retórica. Martin Fowler describe ese esfuerzo extra al modificar un sistema como el «interés» de la deuda técnica: el coste adicional que pagamos cada vez que una decisión interna dificulta el siguiente cambio.
Deja de preguntar cuánto. Pregunta dónde duele.
En vez de preguntar «¿qué código deberíamos limpiar?», prueba con «¿qué parte del sistema nos está haciendo perder más capacidad o asumir más riesgo?». El backlog que sale de esas dos preguntas suele ser muy diferente.
Cuatro preguntas antes de abrir una tarea de refactorización
Cuando detectamos un problema técnico, podemos empezar con cuatro criterios bastante simples.
1. ¿Qué impacto tiene?
No en abstracto.
¿Qué cambia para el producto, para los usuarios o para el equipo si lo resolvemos?
Puede significar entregar funcionalidades más rápido, reducir incidencias, eliminar pruebas manuales, mejorar rendimiento, desbloquear una integración o reducir un riesgo de seguridad.
Si no podemos explicar qué mejora al resolverlo, quizá todavía no tenemos suficiente información para priorizarlo.
2. ¿Qué riesgo estamos aceptando?
Hay deuda que no ralentiza el desarrollo, pero aumenta la probabilidad o el impacto de una caída.
Dependencias sin soporte, backups nunca restaurados, credenciales compartidas, despliegues imposibles de reproducir, ausencia de pruebas en un flujo crítico o conocimiento concentrado en una persona son ejemplos bastante claros.
Que algo no haya fallado todavía no significa que tenga riesgo cero.
3. ¿Con qué frecuencia atravesamos esa zona?
Este criterio cambia completamente la prioridad.
Un módulo difícil de mantener que modificamos una vez cada cuatro años puede convivir con nosotros mucho tiempo. El mismo diseño en un componente que tocamos dos veces por semana se convierte en un impuesto permanente.
Cada funcionalidad paga el peaje. Los bugs también. Y cuando alguien nuevo entra en el equipo, vuelve a pagarlo.
La deuda en una zona de alta frecuencia suele acumular intereses mucho más deprisa.
4. ¿Cuánto cuesta intervenir?
Eliminar deuda también cuesta.
Hay que entender el comportamiento actual, crear pruebas, modificar código, validar integraciones, desplegar, monitorizar y asumir el riesgo del cambio.
Una refactorización de dos días que elimina horas de trabajo repetitivo puede tener un retorno excelente. Una reescritura de seis meses para sustituir un componente estable necesita una justificación bastante más seria que «el código es viejo».
Coste de mantener la deuda frente a coste y riesgo de resolverla.

Una matriz sencilla para priorizar deuda técnica
No hace falta inventar un sistema de puntuación con 47 variables. Para priorizar deuda técnica, basta con empezar por impacto, riesgo, frecuencia y coste.
| Criterio | Bajo | Medio | Alto |
|---|---|---|---|
| Impacto | Apenas perceptible | Genera fricción | Bloquea objetivos o usuarios |
| Riesgo | Consecuencias limitadas | Puede provocar incidencias | Puede comprometer operación, datos o seguridad |
| Frecuencia | Casi nunca se modifica | Cambia ocasionalmente | Se modifica continuamente |
| Coste de intervención | Horas o pocos días | Varias semanas | Proyecto relevante |
El número no toma la decisión por nosotros. Solo obliga a hacer explícito el contexto.
Una matriz no sustituye el criterio
Un 9 sobre 12 no convierte automáticamente una tarea en prioritaria. La puntuación sirve para hacer visible el razonamiento, comparar problemas y detectar desacuerdos. La decisión sigue necesitando contexto técnico y de producto.
Deuda crítica
Tiene un impacto o riesgo que no deberíamos seguir aceptando. Un backup que nadie ha restaurado nunca, una vulnerabilidad conocida, una dependencia crítica fuera de soporte o un proceso cuya caída paraliza una operación importante. Aquí la discusión no debería ser si el código es elegante, sino cuándo podemos reducir el riesgo.
Deuda de alta prioridad
No hay una emergencia, pero pagamos intereses continuamente: un módulo que encarece cada cambio, una integración con pasos manuales o la zona donde aparecen la mayoría de regresiones. No necesita interrumpirlo todo hoy, pero sí debería aparecer en los próximos ciclos.
Deuda oportunista
Sabemos que existe, pero no justifica por sí sola una intervención. Cuando volvamos a tocar esa zona, podemos añadir una prueba, separar una dependencia, eliminar una duplicación, actualizar una librería o documentar una decisión.
Deuda aceptada
Sabemos que el problema existe, entendemos el riesgo y conocemos aproximadamente el coste de resolverlo. Decidimos que, por ahora, hay inversiones mejores. Aceptar conscientemente deuda técnica también es ingeniería.
Aceptar no es esconderlo debajo de la alfombra
Una deuda aceptada debería tener al menos un motivo, un riesgo conocido y una condición de revisión. Si nadie recuerda por qué se aceptó ni cuándo volver a mirarla, ya no es deuda gestionada: es deuda abandonada.

El backlog técnico no debería ser un cementerio
Hay backlogs que contienen tareas como «Refactorizar módulo de pedidos», «Mejorar arquitectura», «Añadir tests», «Actualizar framework» o «Limpiar código antiguo».
Pueden llevar años ahí. No porque nadie vea el problema, sino porque es difícil compararlas con algo como «Permitir que los clientes exporten sus informes».
La funcionalidad tiene un resultado visible. La tarea técnica parece un gasto.
El problema no siempre está en la prioridad. Muchas veces está en cómo explicamos el trabajo.
| Descripción técnica | Consecuencia real |
|---|---|
| Actualizar framework | La versión actual está cerca o fuera de soporte |
| Refactorizar pedidos | Cada cambio obliga a modificar varios componentes |
| Añadir pruebas | Las regresiones consumen horas de validación manual |
| Automatizar despliegue | Cada publicación depende de pasos manuales difíciles de reproducir |
| Documentar integración | Solo una persona sabe recuperarla cuando falla |
Ahora ya no estamos discutiendo sobre belleza del código. Estamos hablando de tiempo, capacidad, riesgo y continuidad.
«Refactorizar» compite mal contra una funcionalidad
«Necesitamos refactorizar este módulo» describe una acción. «Cada cambio en este módulo añade dos días de pruebas y concentra el conocimiento en una persona» describe por qué merece competir por capacidad.

Priorizar deuda técnica no significa frenar el producto
Este es otro falso dilema habitual: producto o calidad.
Si durante meses solo entregamos funcionalidades y nunca reservamos capacidad para mantener el sistema, la velocidad acaba cayendo.
Pero si detenemos el producto durante un trimestre para «dejar el código perfecto», probablemente tengamos otro problema.
La opción sostenible suele estar entre ambos extremos.
- mantenimiento;
- actualizaciones;
- automatización;
- pruebas;
- seguridad;
- observabilidad;
- refactorizaciones pequeñas.
No tiene por qué ser un porcentaje idéntico cada sprint. Un equipo con una migración importante delante necesitará más capacidad técnica; otro que acaba de estabilizar una plataforma nueva quizá necesite menos.
Lo importante es que esta inversión forme parte de la planificación, y no dependa de que sobre tiempo.
Porque nunca sobra.
No conviertas la capacidad técnica en un porcentaje mágico
Reservar un 10 %, un 20 % o cualquier otra cifra puede servir como punto de partida, pero no como dogma. La capacidad necesaria depende del riesgo acumulado, los cambios previstos y el estado real del sistema.
Aprovecha el cambio para mejorar la zona que estás tocando
Una de las mejores oportunidades para pagar deuda aparece cuando el producto ya necesita modificar esa parte del sistema.
Hay que cambiar el proceso de facturación. Perfecto.
Antes de añadir otra condición al bloque que ya tiene diecisiete, quizá sea el momento de cubrir el comportamiento actual con pruebas, separar reglas de negocio, aislar una integración, mejorar los logs o documentar una decisión.
La refactorización ya no es un proyecto paralelo. Forma parte de entregar la nueva funcionalidad de forma sostenible.
Este enfoque evita dos extremos: «No podemos tocar nada porque funciona» y «Antes de añadir la funcionalidad tenemos que reescribir el módulo entero». Normalmente hay un camino intermedio.
¿Cuándo sí merece una intervención específica?
Hay momentos en los que esperar a tocar casualmente una zona no es suficiente.
- una tecnología entra en fin de soporte;
- existe una vulnerabilidad relevante;
- una migración próxima multiplicará el uso de un componente;
- un sistema crítico depende de una persona;
- el rendimiento ya limita el crecimiento;
- el coste de cada cambio está aumentando claramente;
- una integración frágil va a convertirse en pieza central.
En estos casos conviene plantear una intervención explícita.
Pero incluso entonces la primera decisión no debería ser automáticamente «reescribir». Podemos refactorizar, encapsular, actualizar, desacoplar, automatizar, sustituir una pieza o retirar una funcionalidad.
Si el problema está en un sistema heredado, el enfoque cambia todavía más. En esta guía explico cómo modernizar software legacy sin detener el negocio: primero proteger, entender y desacoplar; después decidir qué merece ser sustituido.
Antes de reescribir, reduce la incertidumbre
Una reescritura suele parecer más sencilla cuando todavía no hemos enumerado todo lo que el sistema actual sabe hacer. Antes de elegirla, identifica reglas de negocio, integraciones, datos, casos límite y comportamiento operativo que también tendrás que reconstruir.


La deuda consciente es diferente de la deuda olvidada
A veces asumimos deuda deliberadamente. Necesitamos validar una hipótesis, tenemos una fecha que cumplir o todavía no conocemos suficientemente bien el dominio.
Implementar una solución sencilla para aprender antes de construir algo más complejo puede ser una excelente decisión.
El problema empieza cuando olvidamos que era temporal.
Una deuda consciente debería dejar, como mínimo, cuatro respuestas:
- ¿Qué decisión estamos tomando?
- ¿Por qué la tomamos?
- ¿Qué riesgo aceptamos?
- ¿Qué señal hará que volvamos a revisarla?
No hace falta escribir una tesis. Un ADR pequeño, una tarea bien explicada o una nota junto a la decisión puede ser suficiente.
Deuda consciente en cuatro líneas
Decisión: qué compromiso asumimos. Motivo: qué necesitábamos conseguir. Riesgo: qué puede costarnos después. Revisión: qué evento o señal hará que volvamos a evaluarla.
Lo importante es conservar el contexto.
Porque dentro de dos años alguien encontrará el código, levantará una ceja y preguntará «¿Quién hizo esto?». Y la respuesta menos útil posible será «Ni idea».
Gestionar deuda técnica es un proceso continuo
La deuda no se elimina una vez para siempre.
Un sistema cambia. También cambia el negocio, el equipo, la infraestructura, las integraciones y el coste de nuestras decisiones.
Algo aceptable hoy puede convertirse en crítico dentro de un año. Y una refactorización urgente hace seis meses puede perder toda su importancia si la funcionalidad deja de utilizarse.
Por eso conviene trabajar en ciclo: entender, detectar, priorizar, decidir, invertir, medir y revisar.

No preguntes cuánta deuda técnica tienes
Pregunta dónde la estás pagando.
¿Qué partes cuestan cada vez más de modificar? ¿Dónde se concentran las incidencias? ¿Qué integración depende de una persona? ¿Qué proceso manual aparece en cada despliegue? ¿Qué componente podría convertirse en un riesgo serio dentro de seis meses?
Esas preguntas producen decisiones. Una cifra genérica de «deuda técnica» normalmente no.
El objetivo tampoco debería ser tener un sistema perfecto.
Debería ser tener un sistema que podamos seguir entendiendo, cambiando y operando con un nivel de riesgo razonable.
Algunas deudas habrá que pagarlas ya. Otras convendrá reducirlas poco a poco. Y algunas pueden quedarse exactamente donde están.
No toda la deuda técnica debe pagarse.
Pero si no sabemos cuál tenemos, cuánto nos cuesta y qué riesgo estamos aceptando, entonces ya no la estamos gestionando.
Simplemente estamos esperando a que decida por nosotros.
Una revisión de 30 minutos ya puede cambiar el backlog
Escoge cinco problemas técnicos conocidos y puntúalos de forma aproximada por impacto, riesgo, frecuencia de cambio y coste. No necesitas precisión matemática: necesitas descubrir cuáles lleváis meses llamando «deuda» sin haber decidido realmente qué hacer con ellos.
¿Tienes claro qué deuda técnica merece realmente atención?
Antes de plantear una reescritura completa o llenar el backlog con tareas de «limpieza», puede resultar mucho más útil construir un mapa de deuda técnica priorizado: impacto, riesgo, frecuencia de cambio y coste de intervención.
No para arreglarlo todo.
No para conseguir un código perfecto.
Sino para decidir qué debemos resolver ahora, qué podemos mejorar cuando volvamos a tocar esa zona y qué estamos dispuestos a aceptar conscientemente.
Porque gestionar deuda técnica no consiste en tener menos tareas pendientes.
Consiste en saber qué intereses estamos pagando, cuáles podemos asumir y cuáles empiezan a costarnos demasiado.
La deuda técnica no desaparece. Lo importante es que no sea ella quien termine tomando las decisiones por nosotros.


Deja una respuesta