Cuando la Respuesta Correcta es Código Incorrecto
A veces la decisión correcta de ingeniería es escribir código con el bug deliberadamente — y documentar exactamente por qué.

Punto Clave
Durante una migración de datos financieros, encontramos un macro de trimestre fiscal con un bug de 15 meses. La decisión correcta fue replicarlo intencionalmente, validar paridad al 0.00% de varianza y después corregirlo en un PR separado con documentación completa. Esta es la disciplina de paridad primero — y es lo que hace que la validación sea significativa.
"Necesitamos replicar el bug."
Todos en la llamada guardaron silencio un segundo. No porque la idea fuera descabellada. Sino porque era correcta, y eso incomodaba.
Llevábamos cinco semanas en una migración de datos financieros en una empresa de seguridad en la nube — moviendo cinco años de analítica de ingresos de una plataforma BI legacy a dbt + Snowflake. Teníamos un pipeline validado, una metodología de reconciliación funcionando, y un macro de trimestre fiscal que estaba definitiva y comprobablemente incorrecto. Y la decisión correcta era escribir ese código incorrecto a propósito.
Por qué "solo corrígelo" es el instinto equivocado
El instinto es correcto en aislamiento: encontraste un bug, lo corriges. Ese es tu trabajo.
El problema es que no estás trabajando en aislamiento. Estás migrando un sistema que ha estado corriendo en producción — incorrecto, pero consistentemente incorrecto — por algún período de tiempo. Los sistemas downstream se han adaptado. Los reportes han sido calibrados contra el output con el bug. Finanzas ha estado viendo esos números durante suficiente tiempo como para haber construido intuiciones alrededor de ellos. Comparaciones, metas, presentaciones al consejo — todo desarrollado en relación con la línea base incorrecta.
Cuando corriges el bug en medio de una migración, ahora tienes dos cosas distintas entre tu sistema nuevo y el viejo: la migración en sí, y la corrección del bug. Cada varianza downstream se vuelve ambigua. No puedes saber si cometiste un error de migración o si tu corrección está funcionando como se esperaba. Tu metodología de validación se rompe.
La respuesta limpia es también la contraintuitiva: primero replica el bug. Llega a varianza cero en el output del legacy — incluyendo sus errores. Después corrígelo, en un paso separado, explícito y documentado.
Este principio tiene nombre en nuestro flujo de trabajo: paridad primero, corrección después.
El framework de decisión
No todo bug del legacy merece replicación. Así es como decidimos.
Replica cuando:
- El bug ha estado en producción suficiente tiempo para que los sistemas downstream se hayan adaptado a él
- Reportes, dashboards o modelos financieros downstream referencian directamente el output con el bug
- Necesitas validación de paridad limpia antes de poder certificar la migración con confianza
- La corrección va a producir un cambio visible en el output que Finanzas o los stakeholders necesitan aprobar explícitamente
Corrige de inmediato cuando:
- El bug es reciente (días o semanas), sin adaptación downstream acumulada
- El bug es silencioso — produce output incorrecto que ningún consumidor downstream ha visto nunca
- Ninguna comparación de validación depende del comportamiento con el bug
- La corrección es lo suficientemente aislada como para no crear varianza ambigua
La pregunta del tiempo en producción es la más importante. Un bug activo por 15 meses probablemente generó un año de decisiones contra números incorrectos. Un bug introducido el martes pasado, no. El cálculo es diferente.
El requisito de rastro de auditoría aplica independientemente. Ya sea que repliques o corrijas de inmediato, la decisión necesita documentarse. No solo "replicamos el bug" — sino qué era el bug, cuánto tiempo estuvo activo, qué afectó, y por qué la replicación fue la decisión correcta. Esa documentación te protege a ti y a tu cliente cuando Finanzas pregunta por qué los números de Q2FY25 se ven distintos de las comparaciones históricas.
El macro de trimestre fiscal: una comparación de tres versiones
Aquí está el ejemplo real. El sistema BI legacy de una empresa de seguridad en la nube tenía un macro de conversión de trimestre fiscal con un typo. Q2FY25 estaba definido como iniciando el 2023-05-01 en lugar del 2024-05-01. El resultado: Q2FY25 abarcaba 15 meses en lugar de 3. Esto se descubrió a mediados de diciembre — el bug había estado en producción desde algún momento de 2023.
El error se propagó a funciones de ventana ROW_NUMBER() que usaban la partición por trimestre fiscal para seleccionar el "último mes" de cada trimestre para los cálculos de ARR. Con Q2FY25 abarcando 15 meses, se seleccionaba el mes incorrecto como el valor representativo del trimestre. Las cifras trimestrales de ARR para ese período estaban incorrectas en todos los dashboards que las usaban.
La versión legacy con el bug — lo que el sistema legacy había estado calculando durante 15 meses:
-- Version 1: Legacy system exact replication
-- File: convert_to_fiscal_quarter_legacy_exact.sql
{#
WARNING: REPLICATES LEGACY SYSTEM BUG FOR 100% PARITY
BUG DETAILS:
- Q2FY25 is defined as: period >= '2023-05-01' and period <= '2024-07-01'
- Should be: period >= '2024-05-01' and period <= '2024-07-01'
- This causes Q2FY25 to span 15 months (May 2023 through July 2024)
- This makes ROW_NUMBER() select wrong "last month" for Q2FY25
This bug causes incorrect quarterly ARR values in the legacy system.
We replicate it here for validation parity, but fix in a separate PR.
#}
{% macro convert_to_fiscal_quarter_legacy_exact(date_column) %}
case
-- ... (hardcoded cases through FY24) ...
when {{ date_column }} >= '2024-02-01'
and {{ date_column }} <= '2024-04-01'
then 'Q1FY25'
-- BUG: This should start from 2024-05-01, not 2023-05-01
-- Replicating legacy system typo for validation parity
when {{ date_column }} >= '2023-05-01'
and {{ date_column }} <= '2024-07-01'
then 'Q2FY25'
-- ... (continues through Q4FY26) ...
end
{% endmacro %}
La versión dinámica corregida — lo que el calendario fiscal realmente requiere:
-- Version 2: Correct dynamic version
-- File: convert_to_fiscal_quarter.sql
{#
Fiscal Year Definition:
- Fiscal year starts February 1, ends January 31
- Q1: February - April
- Q2: May - July
- Q3: August - October
- Q4: November - January (spans calendar years)
Dynamic logic works for any date, is fully maintainable.
Results identical to legacy system hardcoded values — except the bug.
#}
{% macro convert_to_fiscal_quarter(date_column) %}
case
when extract(month from {{ date_column }}) in (2, 3, 4) then
'Q1FY' || right(cast(extract(year from {{ date_column }}) + 1 as varchar), 2)
when extract(month from {{ date_column }}) in (5, 6, 7) then
'Q2FY' || right(cast(extract(year from {{ date_column }}) + 1 as varchar), 2)
when extract(month from {{ date_column }}) in (8, 9, 10) then
'Q3FY' || right(cast(extract(year from {{ date_column }}) + 1 as varchar), 2)
when extract(month from {{ date_column }}) in (11, 12) then
'Q4FY' || right(cast(extract(year from {{ date_column }}) + 1 as varchar), 2)
when extract(month from {{ date_column }}) = 1 then
'Q4FY' || right(cast(extract(year from {{ date_column }}) as varchar), 2)
else null
end
{% endmacro %}
Ahora viene la parte de la que nadie escribe. No solo teníamos estas dos versiones. Teníamos una tercera: la versión del bug deliberadamente replicado usada en los modelos de validación. Se parece a la original con el bug — pero los comentarios dejan explícito que esto es intencional, documentado y temporal.
-- Version 3: Intentional replication with full audit trail
-- Used in: fct_arr_validation (validation model only — not production)
{#
INTENTIONAL BUG REPLICATION — FOR VALIDATION PARITY ONLY
Why this exists:
- The legacy system has a typo in Q2FY25 fiscal quarter assignment
- Q2FY25 starts 2023-05-01 in the legacy system; it should start 2024-05-01
- This macro is used ONLY in validation/reconciliation models
- Its purpose is to produce identical output to the legacy system so we can isolate
migration errors from intentional fixes
What happens next:
- Once parity is validated at 0.00% variance using this macro,
fct_arr_v2 is rebuilt using convert_to_fiscal_quarter (correct version)
- The variance introduced by the fix is documented and presented to Finance
- This macro is deprecated after that PR merges
Decision made: [fecha]
Approved by: [client lead]
Tracked in: [el PR de migración]
#}
{% macro convert_to_fiscal_quarter_legacy_exact(date_column) %}
-- Identical logic to the buggy legacy version — intentional.
-- Do not "fix" this macro. See comment above.
case
when {{ date_column }} >= '2024-02-01'
and {{ date_column }} <= '2024-04-01'
then 'Q1FY25'
when {{ date_column }} >= '2023-05-01'
and {{ date_column }} <= '2024-07-01'
then 'Q2FY25'
-- ...
end
{% endmacro %}
El comentario es el trabajo. Cualquier persona que lea ese archivo sabe exactamente qué es, por qué existe, cuándo fue creado, y qué lo hace seguro de deprecar. Sin esos comentarios, el siguiente ingeniero que lo toque o bien "corrige" el bug y rompe la validación, o lo manda a producción pensando que es correcto.
Tres modelos separados usaron este macro de validación. Cada uno validó al 0.00% de varianza contra el sistema legacy antes de que tocáramos la corrección del trimestre fiscal.
Cómo se ve esto en un flujo de validación
La metodología de paridad primero se ejecuta como una secuencia de dos PRs:
PR 1 — Paridad (usa el macro con el bug replicado):
-- Validation query: confirms we've matched legacy output exactly
-- Run against historical data before any fixes are applied
with legacy as (
select
fiscal_quarter,
sum(arr) as legacy_arr
from fct_arr_legacy -- Legacy system output
group by fiscal_quarter
),
migrated as (
select
-- Using the deliberately buggy macro for parity validation
convert_to_fiscal_quarter_legacy_exact(period_month) as fiscal_quarter,
sum(arr) as migrated_arr
from fct_arr_v2_parity
group by fiscal_quarter
)
select
coalesce(l.fiscal_quarter, m.fiscal_quarter) as fiscal_quarter,
l.legacy_arr,
m.migrated_arr,
m.migrated_arr - l.legacy_arr as diff,
round((m.migrated_arr - l.legacy_arr) / nullif(l.legacy_arr, 0) * 100, 4) as pct_diff
from legacy l
full outer join migrated m on l.fiscal_quarter = m.fiscal_quarter
order by fiscal_quarter
-- Expected: all rows show pct_diff = 0.0000
PR 2 — La corrección (cambia al macro correcto, documenta la varianza esperada):
-- After PR 1 is merged and validated at 0.00%:
-- Swap convert_to_fiscal_quarter_legacy_exact → convert_to_fiscal_quarter
-- Re-run the same validation query
-- Q2FY25 will now show a variance — this is expected and correct
-- That variance is the bug being fixed, not a migration error
-- Present to Finance with documentation of the Q2FY25 date boundary correction
El segundo PR produce una varianza conocida, esperada y documentada. Finanzas la ve, la entiende, la aprueba. Ese es el resultado. No silencio. No una corrección invisible. Una decisión.
Lecciones aprendidas
La replicación de bugs es documentación de una decisión, no una falla de ingeniería.
El ingeniero que escribe el bloque de tres comentarios de arriba — "INTENTIONAL BUG REPLICATION — FOR VALIDATION PARITY ONLY" — está haciendo trabajo más útil que el ingeniero que corrige el bug en silencio. Está capturando una decisión que de otro modo sería invisible. Está protegiendo a cada ingeniero futuro de una varianza ambigua. Le está dando a Finanzas una conversación limpia en lugar de una confusa.
La incomodidad que sienten las personas cuando alguien dice "necesitamos replicar el bug" viene de confundir corrección con limpieza. El código correcto no tiene bugs. El código limpio documenta sus decisiones. Un macro temporalmente incorrecto con comentarios perfectos es más limpio que uno silenciosamente correcto que deja preguntas sin respuesta.
La disciplina de paridad primero hace que la validación sea significativa. Si corriges y validas simultáneamente, no puedes interpretar tus números de varianza. Una varianza del 2% después de una migración que también corrigió tres bugs podría significar trabajo excelente o podría significar un error grave — no puedes saber cuál. Sepáralos. Varianza cero en el output con el bug es un hito claro. La varianza de la corrección es un número separado e interpretable.
Documenta la ruta de deprecación antes de hacer merge. El macro con el bug replicado tiene un trabajo que hacer y una fecha en que ese trabajo termina. Escribe el disparador de deprecación en los comentarios en el momento de creación — "deprecado después de que haga merge el PR", "una vez validada la paridad, elimina este macro". Sin eso, el código con el bug replicado tiende a quedarse más tiempo del necesario.
Esta migración encontró 15 bugs en el sistema legacy — el typo del trimestre fiscal fue uno de ellos. Para un relato completo de los otros 14 y cómo la reconciliación sistemática los sacó a la luz, consulta 15 Bugs Silenciosos que Encontramos Migrando una Plataforma BI Financiera. Para la metodología de validación que hizo posibles las comparaciones de paridad, consulta Cómo Validamos una Migración de Datos Financieros hasta el 0.002% de Precisión.
La respuesta correcta a "necesitamos replicar el bug" no es quedarse mirando. Es hacer una pregunta: ¿cuánto tiempo lleva esto en producción?
Quince meses. Entonces sí, lo replicas. Escribes el código incorrecto, escribes los comentarios correctos, y mandas la corrección en el PR donde le corresponde — con visibilidad completa, documentación completa, y un equipo de Finanzas que entiende exactamente qué cambió y por qué.
Temas
Arturo Cárdenas
Fundador y Chief Data Analytics & AI Officer
Arturo es un consultor senior en analítica e IA que ayuda a empresas medianas y grandes a eliminar el caos de datos para desbloquear claridad, velocidad y ROI medible.


