CubeAPM
CubeAPM CubeAPM

What Are the Key ActiveMQ Metrics to Monitor for Performance? 

What Are the Key ActiveMQ Metrics to Monitor for Performance? 

Table of Contents

ActiveMQ exposes all its internal state through JMX (Java Management Extensions). There are three distinct levels of metrics: broker, destination, and JVM. Each level surfaces a different class of failure, and missing any one of them leaves a blind spot. This guide covers what each metric means, what a bad value looks like in production, and how to expose the full set to Prometheus for continuous monitoring and alerting.

One important distinction up front: Apache ActiveMQ (Classic, current stable release 6.2.5) has no native Prometheus endpoint and requires the JMX Prometheus Exporter agent. Apache Artemis (formerly ActiveMQ Artemis, now an independent Apache Top-Level Project since December 2025, at artemis.apache.org) includes a native Prometheus plugin and requires no external agent. The metrics themselves are similar, but the names and setup differ. This guide covers both.

Key Takeaways

  • Apache ActiveMQ (Classic) has no native Prometheus endpoint. Use the JMX Prometheus Exporter agent (latest: v1.3.0, released May 2025), which runs inside the broker JVM and serves metrics on a configurable port at /metrics
  • Apache Artemis has a built-in Prometheus plugin via Micrometer. Enable it with one block in broker.xml. No external agent is needed. Metrics are served at port 8161 under /metrics
  • Metrics live at three levels: broker (JVM process health), destination (queue/topic throughput and backlog), and JVM (heap, GC, threads). All three levels need monitoring. Broker and JVM metrics affect every queue simultaneously
  • The five must-alert metrics are: QueueSize growth rate, MemoryPercentUsage (alert before 70%), StorePercentUsage (alert before 85%), ConsumerCount equal to zero, and AverageEnqueueTime rate of change
  • AverageEnqueueTime is the leading indicator of downstream slowdowns. It rises before the queue depth becomes critical
  • JVM heap exhaustion and full GC pauses manifest as message processing stalls before any broker-level alert fires. JVM metrics are not optional

How ActiveMQ Exposes Metrics

Apache ActiveMQ (Classic): JMX Exporter Agent

Apache ActiveMQ Classic requires the JMX Prometheus Exporter (v1.3.0 as of May 2025) running as a Java agent inside the broker JVM. The agent reads JMX MBeans and serves them at an HTTP endpoint that Prometheus scrapes.

Download the agent JAR:

wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/1.3.0/jmx_prometheus_javaagent-1.3.0.jar

Add the agent to ActiveMQ’s startup configuration. Edit <activemq-install>/bin/env and append to ACTIVEMQ_OPTS:

ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS -javaagent:/opt/activemq/jmx_prometheus_javaagent-1.3.0.jar=9404:/opt/activemq/activemq-config.yml"

Create activemq-config.yml to map ActiveMQ JMX MBeans to Prometheus metrics:

lowercaseOutputName: true

lowercaseOutputLabelNames: true

rules:

  # Broker-level metrics

  - pattern: "org.apache.activemq<type=Broker, brokerName=(.+)><>(.+)"

    name: activemq_broker_$2

    labels:

      broker: "$1"

    attrNameSnakeCase: true

  # Per-destination metrics (queues and topics)

  - pattern: "org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>(.+)"

    name: activemq_queue_$3

    labels:

      broker: "$1"

      destination: "$2"

    attrNameSnakeCase: true

  - pattern: "org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Topic, destinationName=(.+)><>(.+)"

    name: activemq_topic_$3

    labels:

      broker: "$1"

      destination: "$2"

    attrNameSnakeCase: true

Restart ActiveMQ and verify the endpoint is responding:

curl http://localhost:9404/metrics | grep activemq

Apache Artemis: Native Prometheus Plugin

Apache Artemis ships with a native Micrometer-based metrics plugin. Enable it by adding the following to <artemis-instance>/etc/broker.xml inside the <core> block:

<metrics>

  <jvm-memory>true</jvm-memory>

  <jvm-gc>true</jvm-gc>

  <jvm-threads>true</jvm-threads>

  <plugin class-name="org.apache.activemq.artemis.core.server.metrics.plugins.ArtemisPrometheusMetricsPlugin"/>

</metrics>

Restart the broker. Metrics are served at http://localhost:8161/metrics by default. The exact path depends on the metrics.war deployment configured in bootstrap.xml, which is present by default in standard Artemis installations. Verify:

curl http://localhost:8161/metrics | grep artemis

No Java agent or external process is required.

Configure Prometheus to Scrape ActiveMQ

Classic (JMX Exporter on port 9404)

scrape_configs:

  - job_name: activemq-classic

    scrape_interval: 30s

    scrape_timeout: 25s

    static_configs:

      - targets:

          - activemq-host1:9404

          - activemq-host2:9404

        labels:

          env: production

A 30-second scrape interval is recommended for high-cardinality deployments with many destinations. Scraping more frequently increases the JMX attribute resolution load on the broker JVM. On small clusters with under 50 destinations, 15 seconds is acceptable.

Artemis (native plugin on port 8161)

scrape_configs:

  - job_name: activemq-artemis

    scrape_interval: 15s

    metrics_path: /metrics

    static_configs:

      - targets:

          - artemis-host1:8161

          - artemis-host2:8161

        labels:

          env: production

The Key Metrics, What They Mean, and When to Alert

Destination-Level Metrics (Per Queue / Per Topic)

These are the metrics that directly reflect whether your message processing is healthy.

JMX Attribute (Classic)Artemis metricWhat it measuresAlert threshold
QueueSizeartemis_message_countMessages currently in the queue waiting to be consumedAlert when growing continuously for 10 or more minutes
ConsumerCountartemis_consumer_countNumber of active consumers on the destinationCritical alert when it drops to zero for 2 or more minutes
ProducerCountartemis_producer_countNumber of active producers on the destinationAlert on unexpected zero depending on your architecture
EnqueueCountartemis_messages_added_totalTotal messages published (counter). Use rate() to get per-second rateUse to calculate publish rate and compare against dequeue rate
DequeueCountartemis_messages_acknowledged_totalTotal messages consumed and acknowledged (counter)Sustained divergence from enqueue rate means a backlog is building
ExpiredCountartemis_messages_expired_totalMessages that expired before being consumedAny non-zero and rising value on a critical queue warrants investigation
InFlightCountartemis_delivering_countMessages delivered to consumers but not yet acknowledgedA plateau indicates slow or stuck consumers
AverageEnqueueTime(derived from queue metrics)Average time a message spent in the queue before deliveryA rising trend is the earliest warning of consumer slowdown

AverageEnqueueTime deserves special attention. It rises before the queue depth becomes visible. If a downstream service your consumer calls starts slowing down, AverageEnqueueTime will trend upward within minutes while QueueSize may still look normal. Alert on the rate of change, not the absolute value, because the baseline varies by queue.

Broker-Level Metrics

These metrics apply to the entire broker. When they breach thresholds, every queue on that broker is affected.

JMX Attribute (Classic)Artemis metricWhat it measuresAlert threshold
MemoryPercentUsage(JVM heap metrics)Percentage of the broker’s memory limit used by undelivered messagesWarning at 70%, critical at 85%. At 100%, producers are blocked via Producer Flow Control
StorePercentUsageartemis_global_page_store_usagePercentage of the persistent message store usedWarning at 70%, critical at 85%. At 100%, persistent message writes fail
TempPercentUsage(disk metrics)Percentage of temporary store used by non-persistent messagesWarning at 75%
TotalConnectionsCountartemis_connection_countTotal active connectionsAlert on sudden drop (network event) or unexpected spike (connection leak)

MemoryPercentUsage at 100% causes Producer Flow Control to activate, which blocks all producers until memory is released. This is not a graceful slowdown. It is a hard stop. Alert at 70% to give your team time to respond before PFC triggers.

JVM Metrics

Because ActiveMQ runs inside the JVM, JVM resource exhaustion manifests as broker slowdowns before any ActiveMQ-specific metric fires. JVM metrics are not optional.

MetricWhat it measuresAlert threshold
jvm_memory_bytes_used (Classic via JMX exporter) / jvm.memory.used (Artemis via Micrometer)JVM heap memory in useAlert when heap used exceeds 80% of jvm_memory_bytes_max
jvm_gc_collection_seconds_sumCumulative time spent in garbage collectionAlert when GC time rate exceeds 10% of elapsed wall time
jvm_threads_currentCurrent JVM thread countAlert on sustained unexpected growth (thread leak indicator)

Full GC pauses freeze the entire JVM, including message dispatch. A broker that appears stuck with no error in application logs is often experiencing long GC pauses. Correlate GC metrics with any sudden plateau in DequeueCount.

Prometheus Alert Rules

groups:

  - name: activemq

    rules:

      # Queue depth growing continuously (Classic)

      # Uses deriv() because QueueSize is a gauge, not a counter

      - alert: ActiveMQQueueDepthGrowing

        expr: deriv(activemq_queue_queue_size[10m]) > 0

        for: 10m

        labels:

          severity: warning

        annotations:

          summary: "ActiveMQ queue depth is growing"

          description: >

            Queue {{ $labels.destination }} on broker {{ $labels.broker }}

            has been growing for 10 consecutive minutes.

      # Zero consumers on a queue (Classic)

      - alert: ActiveMQQueueNoConsumers

        expr: activemq_queue_consumer_count == 0

        for: 2m

        labels:

          severity: critical

        annotations:

          summary: "ActiveMQ queue has no consumers"

          description: >

            Queue {{ $labels.destination }} on broker {{ $labels.broker }}

            has zero consumers. Messages are accumulating unprocessed.

      # Broker memory pressure (Classic)

      - alert: ActiveMQMemoryHigh

        expr: activemq_broker_memory_percent_usage > 70

        for: 5m

        labels:

          severity: warning

        annotations:

          summary: "ActiveMQ broker memory usage is high"

          description: >

            Broker {{ $labels.broker }} memory is at {{ $value }}%.

            Producer Flow Control activates at 100%.

      # Persistent store pressure (Classic)

      - alert: ActiveMQStoreHigh

        expr: activemq_broker_store_percent_usage > 70

        for: 5m

        labels:

          severity: warning

        annotations:

          summary: "ActiveMQ persistent store usage is high"

          description: >

            Broker {{ $labels.broker }} store is at {{ $value }}%.

            Persistent message writes fail at 100%.

      # JVM heap pressure

      - alert: ActiveMQJVMHeapHigh

        expr: >

          jvm_memory_bytes_used{area="heap"} /

          jvm_memory_bytes_max{area="heap"} * 100 > 80

        for: 5m

        labels:

          severity: warning

        annotations:

          summary: "ActiveMQ JVM heap usage above 80%"

          description: >

            JVM heap on {{ $labels.instance }} is at {{ $value | humanize }}%.

            Full GC pauses will halt message processing.

For Artemis, replace Classic metric names with their Artemis equivalents (artemis_message_count, artemis_consumer_count, etc.) and adjust label names from destination to address and queue as appropriate for your deployment.

Metric Availability: Classic vs Artemis

CapabilityApache ActiveMQ (Classic)Apache Artemis
Prometheus exposure methodJMX Exporter agent (external, v1.3.0)Native plugin via Micrometer (built-in)
Metrics endpointConfigurable port (e.g. 9404) at /metricsPort 8161 at /metrics (default)
Per-destination labelsdestination label via JMX configaddress and queue labels natively
JVM metricsIncluded by JMX exporter automaticallyEnabled per metric category in broker.xml
Unrouted message detectionNot availableartemis_unrouted_message_count fires when messages are published to addresses with no queues
DLQ monitoringVia per-destination metrics on the DLQ nameVia per-queue metrics on the DLQ address

artemis_unrouted_message_count has no Classic equivalent. A non-zero and rising value means messages are being published to addresses that have no queues, which is a silent failure common after misconfigured deployments or schema changes.

Common Setup Problems

ProblemLikely causeFix
No metrics at the JMX exporter endpointAgent JAR path in ACTIVEMQ_OPTS is wrong, or ActiveMQ was not restartedVerify the path, restart ActiveMQ, and check the startup log for javaagent errors
Scrape timeout errors in PrometheusMany destinations causing slow JMX attribute resolutionIncrease scrape_timeout to 25s and scrape_interval to 30s. For very large deployments (500+ destinations), filter the YAML config to only the attributes you need
activemq_queue_queue_size has no destination labelYAML mapping rules not capturing the destination nameVerify the regex in your JMX exporter config matches the actual MBean object names. Use curl http://localhost:9404/metrics to inspect raw output
Artemis metrics missing after enabling the pluginbroker.xml change not saved correctly, or the broker was not fully restartedConfirm the <metrics> block is inside <core>. Check the Artemis log for plugin initialization errors
JVM heap metrics absentJMX exporter running in standalone HTTP server mode instead of Java agent modeRun the exporter as a Java agent (-javaagent: flag). JVM metrics are only available when the exporter runs inside the broker JVM

What Broker Metrics Cannot Tell You

When ActiveMQQueueDepthGrowing or ActiveMQMemoryHigh fires, your metrics show that something is wrong at the broker level. They do not show which consumer application instance is falling behind, which message type is taking the longest to process, or whether the bottleneck is in the consumer’s own code or in a downstream service it calls.

A queue accumulating because of a slow database call inside the consumer looks identical on a broker dashboard to one accumulating because a consumer pod has crashed. The difference matters because the remediation is completely different. One requires fixing or scaling consumer code. The other requires restarting a pod.

CubeAPM instruments your consumer application via OpenTelemetry, regardless of whether your broker is ActiveMQ, Artemis, RabbitMQ, or Kafka, and captures each message processing cycle as a span in the full distributed trace. When a broker alert fires, CubeAPM shows you which consumer instance is slowest, how long each message takes end-to-end, and which downstream service call is responsible. The broker alert tells you something is wrong. CubeAPM tells you what and where. It runs self-hosted inside your own infrastructure at $0.15/GB ingestion pricing, so no data leaves your environment.

Summary

ActiveMQ performance monitoring requires three layers working together: destination-level metrics for queue health, broker-level metrics for resource pressure, and JVM metrics for runtime health. The five metrics that catch most production incidents before they escalate are QueueSize growth rate, MemoryPercentUsage, StorePercentUsage, ConsumerCount equal to zero, and AverageEnqueueTime trend. 

Apache ActiveMQ Classic (latest 6.2.5) requires the JMX Prometheus Exporter agent (v1.3.0). Apache Artemis (now an independent Apache TLP since December 2025) has a native plugin requiring one block of XML configuration.

MetricClassic JMX attributeArtemis metricAlert threshold
Queue depthQueueSizeartemis_message_countGrowing for 10 or more minutes (use deriv())
Consumer countConsumerCountartemis_consumer_countZero for 2 or more minutes
Enqueue vs dequeue rateEnqueueCount / DequeueCountartemis_messages_added_total / artemis_messages_acknowledged_totalSustained divergence
Broker memoryMemoryPercentUsageJVM heap via MicrometerWarning at 70%, critical at 85%
Persistent storeStorePercentUsageartemis_global_page_store_usageWarning at 70%, critical at 85%
Average enqueue timeAverageEnqueueTime(derived from queue metrics)Rising trend for 5 or more minutes
JVM heapjvm_memory_bytes_used (via agent)jvm.memory.used (via Micrometer)Above 80% of max heap
Unrouted messagesNot availableartemis_unrouted_message_countAny non-zero and rising value

Disclaimer: Metric names, JMX MBean patterns, and alert thresholds are verified against Apache ActiveMQ Classic 6.2.5 documentation (activemq.apache.org), Apache Artemis documentation (artemis.apache.org), and the JMX Prometheus Exporter v1.3.0 release (github.com/prometheus/jmx_exporter) as of May 2026. Apache Artemis became an independent Apache Top-Level Project in December 2025 and is no longer part of the ActiveMQ project.

Also read:

RabbitMQ Alerts: How to Alert on RabbitMQ Queue Depth and Consumer Count 

How to Build a RabbitMQ Grafana Dashboard From Scratch 

What Are the Most Important RabbitMQ Metrics to Track?

×
×