Introduction
ActiveMQ destinations (queues and topics) have memory limits. When a destination reaches its limit, producers are blocked if producer flow control is enabled, preventing new messages from being sent until space is available.
Symptoms
Producer blocked:
```bash $ tail -f /var/log/activemq/activemq.log
[WARN] Usage Manager Memory Limit (1048576) reached on queue://orders.queue. Producers will be blocked until memory is freed up. [WARN] Sending message to queue://orders.queue blocked for 30 seconds ```
JMS exception:
javax.jms.ResourceAllocationException: Usage Manager Memory Limit reached.
at org.apache.activemq.broker.region.BaseDestination.blockProducerFlowControl(BaseDestination.java:555)Client timeout:
JMSException: Timed out waiting for space to send message to queue://orders.queueCommon Causes
- 1.Memory limit too low - Destination limit insufficient for message volume
- 2.Slow consumers - Messages pile up because consumers are slow
- 3.No message TTL - Messages never expire, filling up the queue
- 4.Producer flow control enabled - Producers blocked when limit reached
- 5.Large message size - Individual messages consume significant memory
- 6.Dead letter queue overflow - Failed messages accumulating in DLQ
Step-by-Step Fix
Step 1: Check Destination Statistics
```bash # Check queue sizes via JMX activemq-admin query --objname type=Broker,brokerName=localhost,destinationType=Queue,destinationName=* --attribute QueueSize,MemoryPercentUsage
# Via HTTP API curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=orders.queue/QueueSize
# Check memory usage curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost/MemoryPercentUsage
# List all destinations with stats activemq-admin query --objname type=Broker,brokerName=localhost,destinationType=* --attribute Name,QueueSize,MemoryPercentUsage ```
Step 2: Check Producer Flow Control
```bash # Check if producer flow control is enabled curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=orders.queue/ProducerFlowControl
# View current configuration grep -r "producerFlowControl" /etc/activemq/
# In activemq.xml: <policyEntry queue=">" producerFlowControl="true" memoryLimit="10mb"/> ```
Step 3: Increase Memory Limits
```xml <!-- In activemq.xml, update destination policies --> <destinationPolicy> <policyMap> <policyEntries> <!-- Queue policy --> <policyEntry queue=">" producerFlowControl="true" memoryLimit="100mb" maxPageSize="1000"> <pendingQueuePolicy> <storeCursor/> </pendingQueuePolicy> </policyEntry>
<!-- Topic policy --> <policyEntry topic=">" memoryLimit="50mb"> <pendingSubscriberPolicy> <storeDurableSubscriberCursor/> </pendingSubscriberPolicy> </policyEntry>
<!-- Specific queue override --> <policyEntry queue="orders.queue" memoryLimit="500mb" producerFlowControl="true"/> </policyEntries> </policyMap> </destinationPolicy>
<!-- Also update system memory limit --> <systemUsage> <systemUsage> <memoryUsage memoryLimit="1gb"/> <storeUsage storeLimit="10gb"/> <tempUsage tempLimit="500mb"/> </systemUsage> </systemUsage> ```
Step 4: Configure Message TTL
```xml <!-- Set default TTL in destination policy --> <policyEntry queue=">" producerFlowControl="true" memoryLimit="100mb" expireMessagesPeriod="30000"> <deadLetterStrategy> <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/> </deadLetterStrategy> </policyEntry>
<!-- Or set TTL in message producer --> // In Java producer: MessageProducer producer = session.createProducer(queue); producer.setTimeToLive(60000); // 60 seconds producer.send(message);
<!-- Or in connection URI --> <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?wireFormat.maxInactivityDuration=30000"/> ```
Step 5: Disable Producer Flow Control (If Needed)
```xml <!-- Disable producer flow control for specific queue --> <policyEntry queue="urgent.queue" producerFlowControl="false" memoryLimit="50mb"> <pendingQueuePolicy> <storeCursor/> </pendingQueuePolicy> </policyEntry>
<!-- With store cursor, messages go to disk when memory full --> <!-- Producers not blocked, but latency increases -->
<!-- Restart ActiveMQ --> systemctl restart activemq ```
Step 6: Add More Consumers
```bash # Check consumer count curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=orders.queue/ConsumerCount
# Check consumer prefetch curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=orders.queue/MaxConsumer prefetchSize
# Adjust prefetch in consumer connection // Java consumer: connectionFactory.setPrefetchPolicy(new ActiveMQPrefetchPolicy()); connectionFactory.getPrefetchPolicy().setQueuePrefetch(100);
<!-- Or in connection URI --> ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=100"); ```
Step 7: Configure Store Cursor
```xml <!-- Use store cursor to persist overflow messages --> <policyEntry queue=">" memoryLimit="100mb" producerFlowControl="true"> <pendingQueuePolicy> <!-- Store cursor writes overflow to disk --> <storeCursor/>
<!-- Alternative: file cursor for temp storage --> <!-- <fileCursor/> --> </pendingQueuePolicy> </policyEntry>
<!-- This prevents blocking but may slow down under heavy load --> ```
Step 8: Purge Overflowing Queue
```bash # Purge queue via admin console curl -u admin:admin -X POST http://localhost:8161/api/jolokia/exec/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=orders.queue/purge()
# Via activemq-admin activemq-admin purge --queue orders.queue
# Purge all queues activemq-admin purge --queue "*"
# Browse messages before purging activemq-admin browse --queue orders.queue ```
Step 9: Monitor Memory Usage
```bash # Enable JMX monitoring # In activemq.xml: <managementContext> <managementContext createConnector="true" connectorPort="1099"/> </managementContext>
# Monitor via JConsole jconsole service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
# Set up alerts for memory usage # Check memory percentage curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost/MemoryPercentUsage
# Alert when > 80% ```
Step 10: Optimize Message Size
```bash # Check message sizes activemq-admin browse --queue orders.queue --view BodyLength
# Enable message compression // In producer: ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616"); factory.setUseCompression(true);
<!-- Or in activemq.xml transport connector --> <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?wireFormat.useCompression=true"/>
# Reduce message payload size # - Remove unnecessary fields # - Use binary format instead of XML/JSON # - Split large messages ```
Destination Memory Settings
| Setting | Default | Recommended |
|---|---|---|
| memoryLimit | 64mb | 100-500mb |
| producerFlowControl | true | true (or false for critical) |
| maxPageSize | 200 | 1000 |
| expireMessagesPeriod | 30000ms | 30000ms |
Verification
```bash # After configuration changes # Restart ActiveMQ systemctl restart activemq
# Check destination memory usage curl -u admin:admin http://localhost:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=orders.queue/MemoryPercentUsage
# Should be below 80%
# Test message sending activemq-admin send --queue orders.queue --message "test message" --persistent true
# Verify no blocking tail -f /var/log/activemq/activemq.log | grep -i "blocked"
# Check queue statistics activemq-admin query --objname type=Broker,brokerName=localhost,destinationType=Queue --attribute QueueSize,MemoryPercentUsage ```
Prevention
To prevent ActiveMQ destination full issues from recurring, implement these proactive measures:
1. Monitor Queue Depth
groups:
- name: activemq-queues
rules:
- alert: ActiveMQQueueFull
expr: |
activemq_queue_size > 10000
for: 5m
labels:
severity: warning
annotations:
summary: "ActiveMQ queue {{ $labels.queue }} depth exceeds 10000"2. Configure Memory Limits
```xml <!-- activemq.xml --> <systemUsage> <systemUsage> <memoryUsage memoryLimit="512 mb"/> <storeUsage storeLimit="10 gb"/> <tempUsage tempLimit="5 gb"/> </systemUsage> </systemUsageUsage>
<!-- Per-destination limits --> <destinationPolicy> <policyMap> <policyEntries> <policyEntry queue=">" memoryLimit="100mb" producerFlowControl="true"/> </policyEntries> </policyMap> </destinationPolicy> ```
3. Implement Consumer Monitoring
```bash # Check for slow consumers activemq-admin query --objname type=Broker,brokerName=localhost,destinationType=Queue --attribute ConsumerCount,QueueSize
# Alert if consumer count is 0 and queue size > 0 ```
Best Practices Checklist
- [ ] Monitor queue depth with alerts
- [ ] Configure memory limits
- [ ] Monitor consumer count
- [ ] Set up dead letter queues
- [ ] Use message expiration
- [ ] Test under load regularly
Related Issues
- [Fix ActiveMQ Slow Consumer](/articles/fix-activemq-slow-consumer)
- [Fix ActiveMQ Kaha PIndex Corrupted](/articles/fix-activemq-kaha-pindex-corrupted)
- [Fix ActiveMQ JDBC Lock Expired](/articles/fix-activemq-jdbc-lock-expired)
Related Articles
- [Fix Fix Activemq Broker Down Issue in Messaging](fix-activemq-broker-down)
- [Fix ActiveMQ JDBC Lock Expired](fix-activemq-jdbc-lock-expired)
- [Fix ActiveMQ Kaha PIndex Corrupted](fix-activemq-kaha-pindex-corrupted)
- [Fix ActiveMQ Master Slave Failover](fix-activemq-master-slave-failover)
- [Fix ActiveMQ Slow Consumer](fix-activemq-slow-consumer)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix ActiveMQ Destination Full", "description": "Troubleshoot ActiveMQ destination full errors. Configure memory limits, producer flow control, and message TTL.", "url": "https://www.fixwikihub.com/fix-activemq-destination-full", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-04T00:46:58.818Z", "dateModified": "2026-04-04T00:46:58.818Z" } </script>