Como inspeccionar las bandejas de mensajeria

Las cuatro bandejas del patron outbox/inbox se leen via /actuator/message-boxes, un endpoint custom que el arquetipo expone por defecto. La misma seccion de configuracion gobierna el stuck-threshold — global o ajustable por bandeja segun la sensibilidad que cada una tolere.

Para el contrato completo del endpoint y las propiedades disponibles ver Referencia: endpoint message-boxes.

Leer el estado actual

curl http://localhost:8080/actuator/message-boxes

Respuesta tipica:

{
  "events": {
    "outbox": {
      "pending":          12,
      "failed":           0,
      "stuck":            0,
      "stuckThreshold":   "PT5M",
      "oldestPendingAt":  "2026-04-29T20:31:47.812Z",
      "lastProcessedAt":  "2026-04-29T20:42:03.117Z"
    },
    "inbox": {
      "pending":          0,
      "failed":           0,
      "stuck":            0,
      "stuckThreshold":   "PT5M",
      "oldestPendingAt":  null,
      "lastProcessedAt":  "2026-04-29T20:41:57.034Z"
    }
  },
  "commands": {
    "outbox": { ... },
    "inbox":  { ... }
  }
}

Como leer la respuesta

Senal Que indica

pending > 0 y oldestPendingAt reciente

Operacion normal — hay mensajes encolados pero el procesador esta al dia.

pending > 0 y oldestPendingAt mas viejo que stuckThreshold

Equivalente a stuck > 0. El procesador esta atascado o no esta corriendo. Revisar logs del scheduler de outbox/inbox.

failed > 0

Mensajes que excedieron max-retries y quedaron en estado terminal. No se reintentan automaticamente — requieren inspeccion manual y posible reproceso por SQL.

lastProcessedAt muy viejo y pending == 0

La bandeja esta vacia y nada llego en ese intervalo. Puede ser normal si el flujo es esporadico, o puede indicar que el lado productor dejo de generar mensajes.

stuck no es lo mismo que failed.

  • stuck: pending por mas tiempo que stuckThreshold. El mensaje no se proceso — sigue esperando.

  • failed: el mensaje se intento procesar y fallo max-retries veces. Esta en estado terminal.

Un mensaje puede ser ambos transitoriamente (pending durante mucho rato porque no hay scheduler corriendo, despues falla max-retries veces apenas el scheduler vuelve), pero las dos columnas miden cosas distintas y se alertan diferente.

Sobreescribir el stuck-threshold

El threshold default es PT5M (5 minutos) global. Hay dos formas de ajustarlo.

Cambiar el global

Aplica a las cuatro bandejas que no tengan override:

management:
  endpoint:
    health:
      message-boxes:
        stuck-threshold: PT2M

Override por bandeja

Cada combinacion <type>.<box> admite un valor propio:

management:
  endpoint:
    health:
      message-boxes:
        stuck-threshold: PT5M           # default global

        events:
          outbox:
            stuck-threshold: PT30S      # esta bandeja es de baja latencia
        commands:
          inbox:
            stuck-threshold: PT2M       # esta tolera mas latencia

En este ejemplo:

  • events.outbox aplica PT30S (override).

  • commands.inbox aplica PT2M (override).

  • events.inbox y commands.outbox aplican PT5M (caen al global).

Los valores son Duration ISO-8601: PT30S, PT2M, PT15M, PT1H, etc.

Calibrar bajando hasta que aparezcan falsos positivos en horarios de carga normal, despues subir un escalon. El threshold es una alerta — si suena cuando no hay problema, lo silencias y deja de servir.

La logica de resolucion completa esta en Decisiones de monitoreo > stuck-threshold con override.

Filtrar via metricas en lugar del endpoint

Para alertar sobre backlog en Prometheus / Grafana sin polear el endpoint, las metricas messagebox.pending y messagebox.failed estan exportadas con tags type y box. Una alerta tipica para outbox de eventos atascado:

messagebox_pending{type="events", box="outbox"} > 100
  for 2m

stuck no se exporta como metrica — la senal equivalente se deriva combinando messagebox_pending con la persistencia del valor en el tiempo (alerta si se mantiene alto por mas que el threshold).

Ver tambien