La otra mitad del problema de la escritura dual: qué sucede cuando un trabajo termina

<meta content=Descubre qué sucede cuando un trabajo termina y cómo la escritura dual revela su otra mitad. Aprendizajes esenciales para escritores y colaboradores.>

miércoles, 20 de mayo de 2026 • 4 min de lectura • Equipo Q2BSTUDIO

Cuando un trabajo termina: la otra mitad de la escritura dual

En el ecosistema de las aplicaciones modernas, la coherencia entre sistemas distribuidos sigue siendo uno de los desafíos más complejos. Si bien el problema de escritura dual en el lado productor —cuando una operación de negocio y un encolado de trabajo dependen de dos bases de datos distintas— ha recibido mucha atención, la otra mitad del problema suele pasarse por alto: el momento en que un trabajo finaliza. Cuando un worker ejecuta una tarea, actualiza su base de datos y luego notifica al sistema de colas que el trabajo está completo, se abre una ventana de inconsistencia. Si el proceso falla justo después de escribir en la base de datos pero antes de que llegue el acuse de recibo, el trabajo se reprograma y las operaciones de negocio se ejecutan nuevamente. Esto no es un fallo teórico; ocurre con Temporal, BullMQ, Sidekiq y cualquier servicio que separe la confirmación del estado del trabajo de la transacción de la aplicación.

Las soluciones habituales pasan por hacer que los handlers sean idempotentes. Se añaden claves de idempotencia a llamadas externas, se incluyen condiciones WHERE en las actualizaciones o se implementan guardas que verifican si el trabajo ya se realizó. Todo eso funciona, pero es una capa defensiva que responde a un problema estructural: la base de datos y la cola no pueden ponerse de acuerdo sobre si el trabajo ocurrió. En Q2BSTUDIO, cuando desarrollamos aplicaciones a medida para nuestros clientes, nos encontramos con este patrón una y otra vez. La solución no debería ser delegar la responsabilidad al desarrollador, sino eliminar la dualidad desde el diseño.

El enfoque más sólido consiste en ejecutar toda la lógica del handler —lecturas, escrituras, actualización del estado del trabajo y encolado del siguiente paso— dentro de una única transacción de base de datos. Cuando el trabajo solo opera sobre datos locales (inventarios, saldos, estados de máquinas de estados), no hay necesidad de una segunda confirmación: el propio commit de la base de datos marca el trabajo como completado. Si el proceso muere durante la transacción, el motor de base de datos revierte todo y el trabajo se reintenta desde cero. No hay ventana de inconsistencia porque no hay un segundo sistema al que notificar. Esto es especialmente relevante en arquitecturas donde la cola reside en Postgres o SQLite, como sucede con Queuert, pg-boss con configuraciones avanzadas o soluciones de servicios cloud aws y azure que empleamos para despliegues escalables.

Sin embargo, no todos los trabajos son puramente locales. Cuando un handler necesita llamar a una pasarela de pago, enviar un correo o invocar un microservicio, no podemos mantener una transacción abierta durante una operación de red sin arriesgarnos a bloqueos y tiempos de espera. Aquí entra en juego un patrón en dos fases: en una primera transacción se leen los datos necesarios, fuera de la transacción se ejecuta la llamada externa (con su correspondiente idempotencia), y en una segunda transacción se escriben los resultados y se marca el trabajo como completado. Lo crucial es que esa segunda transacción agrupa todas las escrituras: la actualización de los datos de negocio, el cambio de estado del trabajo y cualquier encolado posterior. De este modo, aunque la llamada externa deba ser idempotente, la notificación de finalización nunca queda huérfana. Ambas se confirman juntas o ninguna lo hace.

Este diseño elimina la necesidad de reconciliaciones posteriores, tablas outbox o complicados mecanismos de reenganche. La base de datos relacional demuestra aquí su fortaleza natural como única fuente de verdad. Las herramientas de inteligencia artificial y ia para empresas que integramos en nuestros proyectos también se benefician de esta coherencia, ya que los pipelines de datos y los agentes IA requieren garantías de que cada paso se ejecuta exactamente una vez o que, si se repite, no deja efectos colaterales. La ciberseguridad también gana: un trabajo que nunca se considera completado hasta que todo está confirmado reduce la superficie de ataque de condiciones de carrera.

En la práctica, esto se traduce en una experiencia de desarrollo más predecible. Los equipos dejan de preocuparse por si el acuse de recibo llegó al sistema de colas y se centran en la lógica de negocio. En Q2BSTUDIO aplicamos este principio tanto en proyectos de software a medida como en implementaciones de Power BI donde los procesos de extracción y transformación deben ser robustos frente a fallos de red. También lo utilizamos en despliegues cloud con AWS y Azure, donde la atomicidad basada en transacciones de base de datos sigue siendo más fiable que cualquier mecanismo externo de reconciliación.

La lección es clara: el problema de escritura dual no es inherente a las colas, sino a tener dos sistemas que deben acordar un estado sin compartir una transacción. La solución real no es añadir más capas de idempotencia, sino reducir los sistemas involucrados a uno solo durante los puntos críticos. Cuando eso no es posible, al menos la notificación de finalización debe ser atómica con las escrituras de resultado. Así, el desarrollador no tiene que inventar su propio mecanismo de consistencia; la base de datos ya lo hace por él.

¿UNA PAUSA?

Juega un momento antes de irte

NUESTROS SERVICIOS

Cómo podemos ayudarte

¿Tienes un proyecto en mente?

Cuéntanos tu visión y la convertimos en una solución de software. Sea cual sea el alcance, hacemos realidad tu idea.