Apache ActiveMQ ships in two distinct products that share the name but have different monitoring architectures: ActiveMQ Classic (the original broker, currently on the 5.x and 6.x lines) and Apache Artemis (formerly ActiveMQ Artemis, now an independent Apache project since November 2025, which also powers Red Hat AMQ). Before setting up monitoring, confirm which broker you are running – the monitoring approach for ActiveMQ queues, metric names, and tooling are meaningfully different between the two.
ActiveMQ Classic (5.x / 6.x): Exposes metrics through JMX MBeans. Does not natively publish Prometheus-format metrics. The standard approach for Prometheus integration is the JMX Prometheus Exporter Java agent, which runs inside the broker JVM and converts JMX MBeans to Prometheus exposition format.
Apache Artemis: Ships with a native Micrometer-based metrics plugin that exports Prometheus-format metrics directly, with no external agent required. All Artemis-specific metrics use the artemis. prefix.
Key Takeaways
- ActiveMQ Classic and Apache Artemis are different brokers with different metric names and monitoring architectures – confirm which one you are on before setting up monitoring. ActiveMQ Classic 6.x is a continuation of the Classic codebase, not Artemis
- ActiveMQ Classic does not natively expose Prometheus metrics. Use the JMX Prometheus Exporter Java agent to bridge JMX MBeans to Prometheus
- ActiveMQ Artemis has a native Prometheus plugin – one configuration line in broker.xml enables it with no external tooling needed
- Queue depth (QueueSize in Classic, artemis.message.count in Artemis) is the primary consumer lag indicator for both brokers
- ConsumerCount = 0 on any monitored queue is an immediate alert condition – messages accumulate with no one processing them
- In ActiveMQ Classic, MemoryPercentUsage, StorePercentUsage, and TempStorePercentUsage are broker-wide resource metrics that cause message flow to stop when they hit 100%. Alert before they get there
- Artemis surfaces artemis.unrouted.message.count – messages published to addresses with no queues. This metric has no Classic equivalent and catches a common misconfiguration
ActiveMQ Classic (5.x and 6.x) Monitoring
Primary Monitoring Interface: JMX
Apache ActiveMQ Classic has extensive JMX support. The broker exposes MBeans for the broker itself, each destination (queue and topic), each connection, and each consumer. JMX is enabled by default (useJmx=”true” in activemq.xml).
The MBean hierarchy for a queue is:
org.apache.activemq:type=Broker,brokerName=localhost,
destinationType=Queue,destinationName=YourQueueName
Connect with JConsole for development:# Local connection - no configuration needed
jconsole
# Select the ActiveMQ process from the list of local connectionsRemote JMX connections are not enabled by default for security reasons. For production monitoring, the JMX Prometheus Exporter is the recommended path.
Exposing Classic Metrics to Prometheus: JMX Prometheus Exporter
The JMX Prometheus Exporter is a Java agent that attaches to the broker JVM, reads JMX MBeans, and serves them in Prometheus exposition format on a configurable HTTP port.
Install:
- Download jmx_prometheus_javaagent-<version>.jar from the Prometheus JMX Exporter GitHub releases
- Create a configuration YAML that maps the ActiveMQ MBean patterns to metric names
Minimal configuration for queue and broker metrics (activemq-jmx-config.yaml):
rules:
# Queue depth - most important metric
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>QueueSize'
name: activemq_queue_size
labels:
brokerName: $1
destinationName: $2
help: "Number of messages in the queue (depth)"
type: GAUGE
# Consumer count per queue
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>ConsumerCount'
name: activemq_queue_consumer_count
labels:
brokerName: $1
destinationName: $2
help: "Number of active consumers on the queue"
type: GAUGE
# Enqueue rate (counter, use rate() in Prometheus)
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>EnqueueCount'
name: activemq_queue_enqueue_count_total
labels:
brokerName: $1
destinationName: $2
help: "Total messages enqueued since last restart"
type: COUNTER
# Dequeue rate (counter, use rate() in Prometheus)
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>DequeueCount'
name: activemq_queue_dequeue_count_total
labels:
brokerName: $1
destinationName: $2
help: "Total messages dequeued since last restart"
type: COUNTER
# Inflight messages (delivered to consumer, not yet acked)
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>InFlightCount'
name: activemq_queue_inflight_count
labels:
brokerName: $1
destinationName: $2
help: "Messages sent to consumers but not yet acknowledged"
type: GAUGE
# Expired messages
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>ExpiredCount'
name: activemq_queue_expired_count_total
labels:
brokerName: $1
destinationName: $2
help: "Total messages expired since last restart"
type: COUNTER
# Broker memory usage percentage (0-100)
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>MemoryPercentUsage'
name: activemq_broker_memory_percent_usage
labels:
brokerName: $1
help: "Percentage of broker memory limit in use"
type: GAUGE
# Broker store usage percentage (0-100)
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>StorePercentUsage'
name: activemq_broker_store_percent_usage
labels:
brokerName: $1
help: "Percentage of persistent store space in use"
type: GAUGE
# Temp store usage percentage (0-100)
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>TempPercentUsage'
name: activemq_broker_temp_percent_usage
labels:
brokerName: $1
help: "Percentage of temp store space in use"
type: GAUGE
# Average enqueue time in milliseconds
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>AverageEnqueueTime'
name: activemq_queue_average_enqueue_time_ms
labels:
brokerName: $1
destinationName: $2
help: "Average time messages spend waiting in the queue (ms)"
type: GAUGEEnable the agent in bin/env:
ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS -javaagent:/path/to/jmx_prometheus_javaagent.jar=9404:/path/to/activemq-jmx-config.yaml"Metrics are served at http://broker-host:9404/metrics.
Key JMX MBean Attributes for Classic Queues
These attributes are available on the queue destination MBean:
| JMX Attribute | What it measures | Notes |
| QueueSize | Current number of messages in the queue (depth) | Primary lag indicator |
| ConsumerCount | Messages delivered to consumers, not yet acknowledged | 0 = no one processing |
| EnqueueCount | Total messages enqueued since last restart | Counter – use rate() |
| DequeueCount | Total messages dequeued and acknowledged | Counter – use rate() |
| InFlightCount | Messages delivered to consumers, not yet acked | High value = slow consumers |
| DispatchCount | Total messages dispatched (dequeued + inflight) | Counter |
| ExpiredCount | Messages that expired before delivery | Non-zero = messages being lost |
| AverageEnqueueTime | Average time a message spends waiting (ms) | Rising = consumer slowdown |
| MemoryPercentUsage | % of queue memory limit used | 100% = flow control active |
Broker-level MBean attributes (critical for avoiding full stops):
| JMX Attribute | Alert threshold | What happens at 100% |
| MemoryPercentUsage | > 70% warning, > 85% critical | Broker blocks all producers |
| StorePercentUsage | > 70% warning, > 85% critical | Broker blocks all producers |
| TempPercentUsage | > 75% warning | Broker blocks non-persistent sends |
Important: When MemoryPercentUsage or StorePercentUsage reaches 100%, the broker triggers flow control and blocks all producer connections across the entire broker – not just the queue that caused the pressure. This is a broker-wide outage for producers.
PromQL Alerts for ActiveMQ Classic
# Alert: No consumers on a monitored queue for 2 minutes
activemq_queue_consumer_count == 0
# Alert: Queue depth growing continuously
activemq_queue_size > 0
and (activemq_queue_size - activemq_queue_size offset 10m) > 0
# Alert: Broker memory critical
activemq_broker_memory_percent_usage > 85
# Alert: Persistent store critical
activemq_broker_store_percent_usage > 85
# Alert: Messages expiring (data loss)
rate(activemq_queue_expired_count_total[5m]) > 0
# Alert: Enqueue rate exceeds dequeue rate (backlog growing)
rate(activemq_queue_enqueue_count_total[5m])
- rate(activemq_queue_dequeue_count_total[5m]) > 0Note on EnqueueCount and DequeueCount: These counters reset to zero when the broker restarts. In Prometheus, use rate() or increase() functions for rate-based alerting. For QueueSize, use the value directly as it is a gauge.
JMX MBean Suppression at Scale
At high queue counts (tens of thousands of queues), JMX MBean registration for every consumer and producer becomes expensive. Starting with ActiveMQ Classic 5.12, you can selectively suppress MBean registration:
<managementContext>
<managementContext
suppressMBean="endpoint=dynamicProducer,endpoint=Consumer,
connectionName=*,destinationName=ActiveMQ.Advisory.*"/>
</managementContext>This reduces monitoring overhead while keeping broker and destination-level MBeans visible.
Apache Artemis Monitoring (Formerly ActiveMQ Artemis)
Enabling the Native Prometheus Plugin
Artemis exports metrics via Micrometer. To enable Prometheus-format output, configure a metrics plugin in broker.xml:
<configuration>
<core>
<!-- ... other config ... -->
<metrics>
<jvm-memory>true</jvm-memory>
<jvm-gc>true</jvm-gc>
<jvm-threads>true</jvm-threads>
<file-descriptors>true</file-descriptors>
<plugin class-name="org.apache.activemq.artemis.core.server.metrics.plugins.ArtemisPrometheusMetricsPlugin"/>
</metrics>
</core>
</configuration>After restarting, metrics are served at the broker’s management web server, typically:
http://broker-host:8161/metrics
All Artemis-specific broker metrics use the artemis. prefix. JVM metrics provided by Micrometer do not use the artemis. prefix.
Key Artemis Metrics
Queue-level metrics (tagged with address and queue labels):
| Metric | What it measures |
artemis.message.count | Current messages in the queue (depth) |
artemis.messages.added | Total messages added since startup (counter) |
artemis.messages.acknowledged | Total messages acknowledged (counter) |
artemis.consumer.count | Active consumers currently attached |
artemis.delivering.count | Messages currently being delivered to consumers |
artemis.messages.expired | Total expired messages (counter) |
artemis.scheduled.message.count | Messages scheduled for future delivery |
artemis.durable.message.count | Durable messages currently in queue |
Address-level metrics (tagged with address label):
| Metric | What it measures |
artemis.unrouted.message.count | Messages published to addresses with no queues |
Broker-level metrics (tagged with broker label):
| Metric | What it measures |
artemis.connection.count | Total active connections to the broker |
artemis.total.message.count | Total messages across all queues |
artemis.disk.store.usage | Disk store space used as a fraction (0.0 to 1.0) |
Important note on total message count: Artemis does not expose a single broker-wide total message count metric directly. The documentation explicitly states: “It may appear that some higher-level broker metrics are missing (e.g., total message count). However, these metrics can be deduced by aggregating the lower-level metrics.” Aggregate artemis.message.count across all queues to get the cluster total.
PromQL Alerts for ActiveMQ Artemis
# Alert: No consumers on a queue
artemis_consumer_count{queue="your-queue-name"} == 0
# Alert: Queue depth growing
artemis_message_count > 0
and (artemis_message_count - artemis_message_count offset 10m) > 0
# Alert: Unrouted messages (misconfigured address/queue binding)
artemis_unrouted_message_count > 0
# Alert: Messages expiring (data loss)
rate(artemis_messages_expired[5m]) > 0
# Alert: High disk store usage
artemis_disk_store_usage > 0.85
# Alert: Enqueue rate exceeds ack rate (backlog growing)
rate(artemis_messages_added[5m])
- rate(artemis_messages_acknowledged[5m]) > 0Note on Prometheus metric name format: Micrometer converts . in metric names to _ when exporting to Prometheus. So artemis.message.count becomes artemis_message_count in Prometheus queries.
Metrics Comparison: Classic vs Artemis
| What you need to monitor | ActiveMQ Classic | ActiveMQ Artemis |
| Queue depth | QueueSize (JMX) / activemq_queue_size (Prometheus) | artemis_message_count |
| Consumer count | ConsumerCount (JMX) / activemq_queue_consumer_count | artemis_consumer_count |
| In-flight messages | InFlightCount (JMX) | artemis_delivering_count |
| Messages added rate | EnqueueCount (JMX counter) | artemis_messages_added (counter) |
| Messages processed rate | DequeueCount (JMX counter) | artemis_messages_acknowledged (counter) |
| Expired messages | ExpiredCount (JMX) | artemis_messages_expired |
| Broker memory pressure | MemoryPercentUsage (0-100%) | JVM memory metrics via Micrometer |
| Persistent store pressure | StorePercentUsage (0-100%) | artemis_disk_store_usage (0.0 to 1.0) |
| Unrouted messages | Not available | artemis_unrouted_message_count |
| Prometheus support | Via JMX Prometheus Exporter agent | Native Micrometer plugin |
The Web Console
Both brokers ship with a web console for interactive monitoring:
- ActiveMQ Classic: Management console at
http://broker-host:8161/admin(default credentials: admin/admin – change before production use). Shows queue depth, consumer count, and message rates per destination. - ActiveMQ Artemis: Hawtio-based console at
http://broker-host:8161/console(default credentials: admin/admin – change before production use). Shows per-queue and per-address metrics, active consumers, and message browsing.
The web console is useful for development and ad-hoc investigation. For production alerting and trend analysis, use JMX with Prometheus (Classic) or the native Prometheus plugin (Artemis) combined with Grafana.
How Do I Find Which Application Is Causing an ActiveMQ Queue Backlog?
The queue depth rising on a monitored queue tells you messages are accumulating. It does not tell you which producer is sending faster than consumers can process, whether the consumer is blocked on a downstream call, or which message type is dominating the backlog.
When activemq_queue_size or artemis_message_count climbs on a monitored queue, the debugging path through JMX or Prometheus alone requires correlating producer send rates, consumer ack rates, and broker-side metrics manually – none of which connect to the application request that generated or consumed each message.
CubeAPM instruments your producer and consumer application services via OpenTelemetry and captures each message publish and consume operation as a span in the full distributed trace. When a queue depth alarm fires, the trace in CubeAPM shows which API endpoint is generating the publish load, which consumer service is processing messages, how long each message takes to process end-to-end, and whether the bottleneck is within the consumer’s own logic or in a downstream service it calls. The metric identifies the symptom. The trace identifies where in your application the imbalance originated. Self-hosted inside your own infrastructure, no data leaves your environment.
Summary
| Metric | Classic equivalent | Artemis equivalent | Alert when |
| Queue depth | activemq_queue_size | artemis_message_count | Continuously growing |
| Consumer count | activemq_queue_consumer_count | artemis_consumer_count | = 0 for > 2 minutes |
| In-flight / delivering | activemq_queue_inflight_count | artemis_delivering_count | Growing without dequeue growth |
| Expired messages | activemq_queue_expired_count_total | artemis_messages_expired | Any non-zero rate |
| Broker memory | activemq_broker_memory_percent_usage | JVM heap metrics | > 85% |
| Persistent store | activemq_broker_store_percent_usage | artemis_disk_store_usage | > 85% (Classic) / > 0.85 (Artemis) |
| Unrouted messages | Not available | artemis_unrouted_message_count | > 0 |
Start with queue depth and consumer count alerts for every monitored queue. Add broker memory and store usage alarms to prevent broker-wide flow control events. Enable expired message alerting for any queue with a message TTL configured. Use the web console for ad-hoc investigation and Prometheus plus Grafana for continuous alerting and trend analysis.
Disclaimer: JMX attribute names, Prometheus metric names, configuration examples, and alert thresholds are for guidance only – verify against current ActiveMQ Classic documentation and ActiveMQ Artemis documentation before applying to production. Metric names and behaviors may vary between minor versions. Default web console credentials must be changed before any production deployment. CubeAPM references reflect genuine use cases; evaluate all tools against your own requirements.
Also read:
What Are the Most Important RabbitMQ Metrics to Track?
How to Monitor AWS Fargate Containers with OpenTelemetry
How to Monitor AWS DynamoDB Read/Write Capacity and Throttles





