Por qué esto es importante
Cada transacción en Midaz crea operaciones de saldo que Midaz debe persistir. En el modo síncrono predeterminado, Midaz las escribe directamente en la base de datos durante el ciclo de la solicitud. Esto es aceptable para volúmenes moderados. A escala — miles de transacciones por segundo — se convierte en el cuello de botella. El Bulk Recorder acumula mensajes y los escribe en lotes. Hace menos viajes de ida y vuelta a PostgreSQL, reduce la contención de bloqueos y aumenta el rendimiento. Las cargas de alto volumen son las que más ganan: pagos masivos, liquidaciones por lotes y procesamiento de pagos en tiempo real. Para estrategias más amplias para escalar Midaz, consulta Estrategias de escalabilidad.
Cómo funciona
El Bulk Recorder se sitúa entre el consumidor de RabbitMQ y la capa de base de datos. No inserta cada mensaje de inmediato. En su lugar, recopila los mensajes en un búfer y los descarga bajo dos condiciones:
- Tamaño de lote alcanzado — el búfer se llena hasta el tamaño configurado.
- Tiempo de espera agotado — el tiempo de espera de descarga configurado expira, incluso si el búfer no está lleno.
Figura 1. Flujo de extremo a extremo del Bulk Recorder entre RabbitMQ y PostgreSQL.
- RabbitMQ entrega los mensajes al BulkCollector uno a la vez — Mensaje 1, Mensaje 2, hasta el Mensaje N.
- El BulkCollector los mantiene en memoria en lugar de una escritura por mensaje. Recopila hasta que el lote se llena o el tiempo de espera de descarga expira.
-
El BulkCollector envía un INSERT en lote fragmentado a PostgreSQL. Midaz divide los lotes grandes en fragmentos que respetan los límites de parámetros de PostgreSQL. Cada fragmento usa
ON CONFLICT (id) DO NOTHING, por lo que los reintentos y las entregas duplicadas se mantienen seguros. - PostgreSQL confirma la escritura y almacena los datos.
- El BulkCollector confirma cada mensaje de vuelta a RabbitMQ después de la escritura. Los confirma uno a la vez, no en un único ACK conjunto. Esto evita que un canal compartido confirme mensajes que otros workers aún procesan.
Habilitar el Bulk Recorder
El modo en lote requiere el modo asíncrono. La configuración explícita del Bulk Recorder es opcional porque está habilitada de forma predeterminada:
RABBITMQ_TRANSACTION_ASYNC=true, el Bulk Recorder está habilitado de forma predeterminada; configura BULK_RECORDER_ENABLED=false para procesar los mensajes en cola individualmente. Sin modo asíncrono, Midaz persiste las transacciones directamente en lugar de consumir mensajes en cola.
Configuración
Tamaño de lote calculado automáticamente
CuandoBULK_RECORDER_SIZE se establece en 0 (el valor predeterminado), Midaz deriva el tamaño del lote:
Ajuste para tu carga de trabajo
Las dos palancas principales son el tamaño del lote y el tiempo de espera de descarga. El equilibrio correcto depende de tu prioridad: latencia o rendimiento.
Baja latencia (procesamiento en tiempo real)
Mantén los lotes pequeños y los tiempos de espera cortos. Midaz persiste los mensajes rápidamente, incluso cuando los lotes no están llenos.Alto rendimiento (operaciones por lotes)
Lotes más grandes y tiempos de espera más largos maximizan la eficiencia de la base de datos. Usa esto para pagos masivos, liquidaciones de fin de día o cargas de trabajo de migración.Garantías de seguridad
El Bulk Recorder se mantiene seguro en toda condición:
Idempotencia
Cada inserción en lote usaON CONFLICT (id) DO NOTHING. Si un mensaje llega dos veces — por un reintento, una re-entrega o un fallo de red — PostgreSQL descarta el duplicado. No obtienes corrupción de datos ni violaciones de restricciones.
Prevención de deadlocks
Antes de cada inserción en lote, Midaz ordena los IDs de los registros. Todos los escritores concurrentes adquieren entonces los bloqueos en el mismo orden. Esto elimina la fuente más común de deadlocks de PostgreSQL en alta concurrencia.Fragmentación interna
Midaz divide los lotes grandes en fragmentos que caben dentro del límite de 65.535 parámetros por consulta de PostgreSQL:
Midaz maneja esta fragmentación por ti. Cada
INSERT incluye como máximo 1.000 filas. BULK_RECORDER_MAX_ROWS_PER_INSERT no se aplica actualmente al tamaño del fragmento de PostgreSQL.
Cuándo usar
Usa el Bulk Recorder cuando:
- Procesas altos volúmenes de transacciones (cientos o miles por segundo).
- Tu carga de trabajo incluye operaciones por lotes como pagos masivos, liquidaciones o migraciones de datos.
- Ya usas procesamiento asíncrono de transacciones (
RABBITMQ_TRANSACTION_ASYNC=true). - Quieres reducir la carga de la base de datos y la presión de conexión.
- Tu volumen es lo suficientemente bajo como para que las inserciones individuales no sean un cuello de botella.
- Necesitas garantías estrictas de ordenamiento por mensaje que el procesamiento por lotes rompería.
- Depuras el procesamiento de transacciones y quieres un flujo más simple, mensaje por mensaje.

