Por qué esto importa
Un cliente envía una transacción. Midaz debe hacer dos cosas: validarla y persistir el resultado. En el modo síncrono, ambos pasos se ejecutan en la misma solicitud. El cliente espera hasta que cada escritura llega a la base de datos antes de recibir una respuesta. Este modelo es simple y predecible, pero tiene un límite. Con un volumen alto, las escrituras a la base de datos se convierten en el cuello de botella. Cada transacción retiene una conexión, espera bloqueos y compite por I/O. El modo asíncrono rompe esa dependencia. Midaz valida la transacción, devuelve la respuesta de inmediato y persiste los datos en segundo plano mediante RabbitMQ. El cliente obtiene respuestas más rápidas. Con el procesamiento asíncrono habilitado, el Bulk Recorder agrupa las inserciones de forma predeterminada. Define
BULK_RECORDER_ENABLED=false para persistir los mensajes en cola de forma individual.
Para una guía más amplia de escalabilidad, consulta Estrategias de escalabilidad.
Cómo funciona
Modo síncrono (predeterminado)
Midaz valida la transacción y la escribe directamente en PostgreSQL dentro del mismo ciclo de solicitud. La API envía su respuesta solo después de que se completa cada operación de base de datos.Figura 1. Flujo de transacción síncrono. El cliente espera hasta que se confirma la escritura en la base de datos.
-
El cliente envía un
POST /transactiona la API de Midaz. - La API valida la solicitud. Aquí ejecuta la validación de forma de la solicitud, las verificaciones de saldo y la aplicación de límites.
- La API escribe en PostgreSQL. Persiste la transacción y sus operaciones dentro del mismo ciclo de solicitud.
- PostgreSQL confirma la escritura. Confirma todos los registros.
-
La API devuelve
201 Createdal cliente con la transacción creada. La respuesta sale del servidor solo después de que la base de datos confirma todo. La respuesta lleva el estado transitorioCREATED. Midaz promueve la transacción aAPPROVEDde forma asíncrona después del procesamiento de saldos. No trates el201como aprobación final. Espera a que el estado llegue aAPPROVEDantes de tratar la transacción como liquidada.
- El tiempo de respuesta incluye la latencia de la escritura en la base de datos.
- Cada transacción es una operación de base de datos independiente.
- Más simple de razonar. La respuesta muestra exactamente lo que Midaz persiste.
Incluso en modo síncrono, Midaz actualiza los saldos de forma atómica en Redis durante la solicitud. Redis es la fuente autoritativa de los saldos. La escritura anterior persiste la transacción y sus operaciones, no las filas de saldo en Postgres. El worker de sincronización de saldos, siempre activo, reconcilia esas filas (consulta Sincronización de saldos).
Modo asíncrono
Midaz valida la transacción de la misma forma. En lugar de una escritura directa a la base de datos, Midaz publica un mensaje en RabbitMQ. Un consumidor en segundo plano recoge el mensaje y maneja la persistencia por separado.Figura 2. Flujo de transacción asíncrono. El cliente recibe una respuesta en cuanto se publica el mensaje, y la persistencia ocurre en segundo plano.
-
El cliente envía un
POST /transactiona la API de Midaz. - La API valida la solicitud. Ejecuta la validación de forma de la solicitud, las verificaciones de saldo y la aplicación de límites exactamente igual que en el modo síncrono.
- La API publica el payload de la transacción en RabbitMQ en lugar de una escritura directa a la base de datos.
-
La API devuelve
201 Createdal cliente en cuanto la cola acepta el mensaje. El cliente no espera la persistencia en la base de datos. La respuesta lleva el estado transitorioCREATED. Midaz promueve la transacción aAPPROVEDde forma asíncrona después del procesamiento de saldos. No trates el201como aprobación final. Espera a que el estado llegue aAPPROVEDantes de tratar la transacción como liquidada. - RabbitMQ entrega el mensaje a un consumidor en segundo plano, desacoplado de la solicitud de la API.
- El consumidor escribe en PostgreSQL. Persiste la transacción y sus operaciones a partir del mensaje en cola. El worker de sincronización de saldos coordina las actualizaciones de saldo y mantiene los saldos consistentes en ambos modos (consulta la sección Sincronización de saldos).
- El tiempo de respuesta excluye la latencia de la escritura en la base de datos. El cliente espera solo la validación y la publicación en la cola.
- Midaz serializa los mensajes con MessagePack para un transporte compacto y eficiente.
- Los consumidores en segundo plano escriben en la base de datos a su propio ritmo, con reintentos. Las inserciones por lote requieren que el Bulk Recorder esté habilitado.
Resiliencia integrada
Si RabbitMQ no está disponible cuando el modo asíncrono intenta publicar un mensaje, Midaz intenta una escritura directa a la base de datos. Si esa escritura falla, Midaz devuelve el error de la base de datos. Esto significa:
- Durante una interrupción de la cola, Midaz intenta escribir directamente en la base de datos.
- El cliente puede recibir un error si la escritura de reserva a la base de datos también falla.
- Midaz registra la falla de la cola y, si la escritura directa también falla, la falla de la escritura de reserva, para que tu equipo de operaciones pueda investigarlas.
Habilitar el modo asíncrono
Define una variable de entorno en la aplicación del ledger:
false (el valor predeterminado), todas las transacciones usan procesamiento síncrono y persisten directamente en PostgreSQL. El bootstrap actual del Ledger de todos modos inicializa RabbitMQ y conecta su consumidor.
Con true, el ledger publica los payloads de transacción en el exchange de RabbitMQ configurado. Un consumidor en segundo plano maneja entonces la persistencia.
Configuración de RabbitMQ
El modo asíncrono usa la siguiente configuración de RabbitMQ (todo en el
.env del ledger):
Sincronización de saldos
Un worker dedicado de sincronización de saldos coordina las actualizaciones de saldo. Usa Redis como capa de coordinación. Este worker se ejecuta tanto en modo síncrono como en modo asíncrono. Mantiene los saldos consistentes incluso cuando varios consumidores procesan mensajes al mismo tiempo.
El worker de sincronización de saldos se ejecuta automáticamente en ambos modos. No necesitas configuración adicional más allá de contar con una instancia de Redis disponible.
Circuit breaker de RabbitMQ
Cuando habilitas el modo asíncrono, Midaz depende de RabbitMQ para la persistencia de transacciones. Un circuit breaker integrado protege contra interrupciones del broker. Monitorea el estado de la conexión con RabbitMQ y falla rápido cuando el broker cae. Esto evita la acumulación de solicitudes y las fallas en cascada. El circuit breaker está activo en la ruta de RabbitMQ de tenant único. El RabbitMQ multi-tenant usa en su lugar la gestión de conexiones por tenant. El circuit breaker sigue el modelo estándar de tres estados:
- Closed (normal): las solicitudes fluyen hacia RabbitMQ. El breaker cuenta las fallas.
- Open (activado): el breaker no contacta a RabbitMQ. Midaz evita el broker e intenta una escritura directa a la base de datos para cada transacción asíncrona. Si esa escritura falla, Midaz devuelve el error de la base de datos. Un verificador de estado en segundo plano monitorea el broker e intenta la recuperación.
- Half-open (en prueba): el breaker permite el paso de un número limitado de solicitudes para probar la recuperación de RabbitMQ. Si tienen éxito, el circuito se cierra. Si fallan, se vuelve a abrir.
- El número de fallas consecutivas alcanza el umbral, O
- El ratio de fallas supera el porcentaje configurado dentro de la ventana de conteo
Configuración del circuit breaker
Cuando el circuito está abierto, Midaz intenta escrituras directas a la base de datos para las transacciones asíncronas. Si una escritura directa falla, Midaz devuelve el error de la base de datos. La reserva no garantiza la entrega de la transacción durante interrupciones del broker.
Cómo se conecta el modo asíncrono con Bulk Recorder
El modo asíncrono y el Bulk Recorder trabajan juntos:
- El modo asíncrono desacopla la respuesta de la API de la persistencia. Las transacciones van a RabbitMQ en lugar de ir directamente a PostgreSQL.
- Bulk Recorder optimiza cómo el consumidor escribe esos mensajes en la base de datos. Agrupa varios mensajes en inserciones masivas únicas.
BULK_RECORDER_ENABLED=false. Sin el modo asíncrono, la persistencia de transacciones usa escrituras directas a la base de datos y no hay cola de transacciones para agrupar.
Cuándo usar el modo asíncrono
Usa el modo asíncrono cuando:
- Necesitas tiempos de respuesta de API más bajos para la creación de transacciones.
- Tu carga de trabajo implica volúmenes altos de transacciones (cientos o más por segundo).
- Ejecutas operaciones por lote como pagos masivos o liquidaciones.
- Quieres desacoplar tu capa de API del rendimiento de la base de datos.
- Necesitas persistencia de transacciones directa, ligada a la solicitud.
- El volumen de transacciones es bajo o moderado.
- Quieres que una respuesta exitosa de la API signifique que Midaz ya persistió los datos.
- Trabajas en un entorno de desarrollo o pruebas donde la simplicidad importa más que el throughput.

