Prev Next

Integration / ActiveMQ Interview Questions Intermediate

Could not find what you were looking for? send us the question and we would be happy to answer your question.

1. What is the difference between Queue and Topic in ActiveMQ?

Queues and Topics implement JMS's two messaging models and behave very differently once more than one consumer is involved.

QueueTopic
Point-to-point deliveryPublish-subscribe delivery
Exactly one consumer gets each messageEvery active subscriber gets each message
Message stays until a consumer takes and acks itNon-durable: message is lost if no subscriber is connected
Good for distributing work across a worker poolGood for broadcasting events or notifications

Both destination types are created and used through the same JMS Session API; only the destination object and its delivery semantics differ.

This distinction also shapes how you reason about scaling: adding more consumers to a Queue increases throughput by splitting the same work among more workers, while adding more subscribers to a Topic increases total delivery volume, since each subscriber gets a full copy rather than a share. Choosing wrong is a common interview trap - using a Topic for a work queue means every worker processes every message instead of splitting the load, and using a Queue for a broadcast means only one interested service ever gets notified.

In which destination can multiple consumers all receive the same message?
Which destination guarantees only one consumer processes a given message?

2. What is the difference between ActiveMQ and Kafka?

ActiveMQ is a traditional JMS-compliant message broker built for flexible routing (queues, topics, virtual destinations) and enterprise integration patterns. Kafka is a distributed, log-based streaming platform built for very high-throughput, ordered, replayable event streams.

ActiveMQ typically removes a message once it's acknowledged; Kafka retains messages on disk for a configured retention period regardless of consumption, so multiple independent consumer groups can replay the same log at their own pace. ActiveMQ scales mainly through networks of brokers or vertical scaling, while Kafka is designed from the ground up to scale horizontally via partitioned topics across a cluster. On ordering, ActiveMQ can guarantee order within a Queue, whereas Kafka guarantees order only within a partition.

AspectActiveMQKafka
ModelMessage broker (JMS)Distributed commit log
RetentionDeleted after acknowledgmentTime/size-based retention
ThroughputModerateVery high
OrderingPer QueuePer partition
ReplayNot built-inNative

Choose ActiveMQ when you need per-message transactional semantics, complex routing, or protocol variety (JMS/AMQP/MQTT/STOMP). Choose Kafka when you need to process massive event volumes, replay history, or feed multiple downstream systems from the same stream.

Which system retains messages on disk for a set period regardless of consumption?
Which system is JMS-compliant out of the box?

3. Why do we use persistent messages in ActiveMQ?

Persistent messages are written to the broker's storage (KahaDB, JDBC, etc.) before delivery is confirmed, so a message survives a broker crash or restart. Without persistence, an in-flight message living only in memory is lost the moment the broker goes down.

Persistent delivery costs some throughput because of the disk write, so its use is a deliberate trade-off: pick it for anything you can't afford to lose (payments, orders), and let genuinely disposable data (like a live metrics feed) go non-persistent for maximum speed. ActiveMQ makes this choice per-message via DeliveryMode.PERSISTENT / NON_PERSISTENT, so a single application can mix both depending on how critical each message stream is.

In code, this is set on the MessageProducer via setDeliveryMode(DeliveryMode.PERSISTENT), or per-message on the send call itself, so the same producer can send a mix of critical and disposable messages to different destinations without needing two separate connections. It's worth noting that persistence protects against broker restarts and crashes, but it doesn't by itself guarantee exactly-once delivery to the consumer - a redelivered persistent message can still be processed twice if the consumer's acknowledgment is lost in transit.

What is the trade-off of using persistent messages?
Which delivery mode survives a broker restart?

4. How does message acknowledgment work in ActiveMQ?

When a consumer receives a message, the broker marks it as dispatched but keeps it in its store until an acknowledgment arrives, rather than deleting it right away.

sequenceDiagram Producer->>Broker: send(message) Broker->>Consumer: dispatch(message) Consumer->>Broker: acknowledge() Broker->>Broker: remove from store

The exact trigger for that acknowledge() call depends on the session's ack mode - automatic right after delivery, explicit via client code, or tied to a transaction commit. If the consumer disconnects before acknowledging, the broker treats the message as still pending and redelivers it once a consumer is available again.

DUPS_OK_ACKNOWLEDGE relaxes this slightly by letting the client acknowledge lazily and in batches for better throughput, accepting that a crash between processing and the lazy ack could cause a duplicate delivery. SESSION_TRANSACTED ties acknowledgment to a transaction boundary instead of an individual call, so a whole batch of receives is acknowledged, or rolled back, together as one unit whenever commit() or rollback() is invoked.

What does the broker do with a message before acknowledgment arrives?
What happens if the consumer disconnects before acknowledging?

5. When should you use a Durable Subscriber over a plain consumer?

Use a durable subscriber when the receiver is a Topic subscriber that must never miss messages published while it's offline - for example, an audit trail, a billing reconciliation job, or a cache-warming service that must reflect every event even after a restart or network blip.

A plain, non-durable topic subscriber only gets what's published while it's actively connected, so any gap in connectivity means a permanent gap in its view of the stream. The trade-off is that the broker must retain unacknowledged messages for a durable subscriber indefinitely, or until a configured expiry, consuming storage even while the subscriber is offline. That's why it isn't the default choice for every topic consumer - only for ones where completeness matters more than storage overhead.

It's worth contrasting this with Virtual Topics, which achieve similar no-message-loss guarantees for multiple consumer groups without the per-client durable subscription bookkeeping - durable subscribers remain the right tool specifically when you need classic JMS topic semantics, such as selectors scoped to one named subscription.

What must the broker do for a durable subscriber while it's offline?
A durable subscriber is best suited for...

6. What happens when a consumer fails to acknowledge a message?

If a consumer disconnects, crashes, or times out without sending an acknowledgment (in CLIENT_ACKNOWLEDGE or transacted mode), ActiveMQ treats the message as still pending and redelivers it - either to the same consumer on reconnect or to another available consumer on the same queue.

Each redelivery increments a counter tracked in the message's JMSXDeliveryCount property. Once that counter exceeds the redelivery policy's maximumRedeliveries (default 6), the broker stops retrying and routes the message to the Dead Letter Queue instead of looping forever. This protects the system from a single poison message endlessly blocking a queue while still giving transient failures, like a brief network blip or a slow database call, a chance to succeed on retry.

The exact redelivery delay is also configurable, typically starting small and increasing with an exponential back-off, so a consumer experiencing a brief hiccup gets a quick retry while one stuck in a longer outage doesn't get hammered with immediate redeliveries every few milliseconds.

What happens after a message exceeds maximumRedeliveries?
Which property tracks how many times a message has been redelivered?

7. How is message ordering guaranteed in ActiveMQ?

Within a single Queue with a single active consumer, ActiveMQ preserves the order messages were sent in - FIFO delivery is the default behavior. As soon as multiple consumers listen on the same queue, ActiveMQ load-balances messages across them, so strict global ordering across consumers is no longer guaranteed, only per-consumer ordering of whatever each one happens to receive.

Message priority (JMSPriority) and expiration can also reorder delivery, since a higher-priority or soon-to-expire message can jump ahead. If an application needs strict ordering with multiple parallel workers, a common pattern is to route related messages (for example, the same customer ID) to the same queue, or use message groups, which pin all messages sharing a group ID to one consumer.

It's also worth knowing that ordering guarantees apply only within a single destination; there's no cross-queue or cross-topic ordering promise in ActiveMQ, so an application that needs strict ordering across several related destinations has to build that coordination itself, typically by funnelling related events through one queue via a shared key.

With a single consumer on a queue, ActiveMQ delivers messages in...
What technique pins related messages to one consumer for ordering?

8. What is the difference between AUTO_ACKNOWLEDGE and CLIENT_ACKNOWLEDGE?

These two modes differ in who triggers the acknowledgment and how much control the application has over it.

ModeTriggerRisk / Benefit
AUTO_ACKNOWLEDGERight after receive()/onMessage() returnsSimple, but can lose messages if processing fails after the ack is already sent
CLIENT_ACKNOWLEDGEExplicit acknowledge() callFull control; acknowledging one message acks all prior unacked messages in that session

CLIENT_ACKNOWLEDGE is useful when you want to batch several messages before committing the acknowledgment, while AUTO_ACKNOWLEDGE suits simple, low-risk consumers where speed of development matters more than fine-grained control.

A subtle but important detail: even in CLIENT_ACKNOWLEDGE mode, ActiveMQ doesn't require calling acknowledge() on every single message - calling it once after processing a batch acknowledges that entire batch, which is why this mode is popular for consumers that intentionally process several messages before confirming completion, trading a little more risk on failure for noticeably less network chatter with the broker.

Calling acknowledge() in CLIENT_ACKNOWLEDGE mode acknowledges...
What risk does AUTO_ACKNOWLEDGE carry?

9. Why should you enable producer flow control?

Producer flow control stops a fast producer from overwhelming the broker or a slow consumer when memory or storage limits on a destination are close to being hit. Instead of letting the broker's memory fill up and eventually error out or crash, ActiveMQ can pause the producer's send() call until space frees up, applying back-pressure at the source of the problem.

This is valuable in systems where producers can generate messages far faster than downstream consumers can process them. Without flow control, unbounded queues quietly grow until the broker runs out of memory or disk, which is a much harder failure to recover from than a temporarily slow producer.

Flow control is configured per destination policy in activemq.xml via producerFlowControl and memoryLimit attributes, so different queues can have different tolerances - a low-priority logging queue might be allowed to block aggressively, while a payments queue might be given a much larger memory budget so it rarely, if ever, throttles.

What does producer flow control do when a destination nears its memory limit?
What problem does flow control prevent?

10. How do you configure a Dead Letter Queue policy?

Redelivery attempts and DLQ routing are configured together in activemq.xml:

<redeliveryPolicy maximumRedeliveries="3" initialRedeliveryDelay="1000"
                  backOffMultiplier="2" useExponentialBackOff="true"/>

<deadLetterStrategy>
  <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/>
</deadLetterStrategy>

maximumRedeliveries controls how many attempts happen before a message is considered undeliverable. individualDeadLetterStrategy routes each source destination to its own DLQ.<name> queue instead of one shared ActiveMQ.DLQ, making it much easier to trace which queue a failed message originally came from.

Redelivery delay grows with each attempt when useExponentialBackOff is enabled, starting at initialRedeliveryDelay and multiplying by backOffMultiplier on every retry, up to an optional maximumRedeliveryDelay ceiling. This spacing gives transient issues, like a brief database outage, more time to resolve between attempts instead of hammering the same failing operation immediately. Once individualDeadLetterStrategy is enabled, an operator can look directly at a queue like DLQ.OrdersQueue to know exactly which upstream destination a poisoned message originated from, rather than digging through one shared ActiveMQ.DLQ full of unrelated messages from every queue on the broker.

What does individualDeadLetterStrategy provide over the default shared DLQ?
Which element controls how many redelivery attempts happen before DLQ?

11. When would you choose Virtual Topics over regular Topics?

Choose Virtual Topics when multiple independent consumer groups each need to reliably receive every message, with the durability and load-balancing guarantees of a Queue, without configuring true durable subscriptions for every group.

Each consumer group listens on its own Consumer.<name>.VirtualTopicName queue, and ActiveMQ fans out one publish to all of those queues automatically; within a group, multiple worker instances share the load like a normal queue. This avoids the operational overhead of managing durable subscriber client IDs while still guaranteeing no group misses a message, which plain non-durable topic subscribers would.

A concrete example: an order-placed event published to a Virtual Topic might need to reach both a shipping consumer group and an analytics consumer group. Each group gets its own queue-backed subscription, and either group can run multiple worker instances that share the load internally, all while both groups independently guarantee they'll never miss an order event.

What naming pattern do Virtual Topic consumer queues follow?
What guarantee do Virtual Topics provide that plain non-durable Topics don't?

12. What is the difference between ActiveMQ Classic and ActiveMQ Artemis?

ActiveMQ Classic (5.x) is the original, mature JMS broker with KahaDB persistence. Artemis is a newer broker built on the HornetQ codebase donated to Apache, using an asynchronous journal-based storage model and a native Core protocol, while still supporting OpenWire, AMQP, MQTT, and STOMP for compatibility.

AspectClassic (5.x)Artemis
OriginOriginal ActiveMQHornetQ-based, donated to Apache
PersistenceKahaDB / JDBCAsynchronous journal
PerformanceGoodGenerally higher throughput
StatusMature, maintainedPositioned as long-term successor

Artemis generally offers better throughput and lower latency due to its non-blocking I/O journal, though Classic remains widely deployed and still fully supported.

Migration between the two isn't always a drop-in replacement - Artemis's default addressing model and some configuration file formats differ from Classic's, so teams typically plan a phased migration, often running both side by side temporarily via a bridge, rather than swapping the broker binary in place. New deployments are increasingly steered toward Artemis, but Classic's long track record still makes it a common, fully supported choice for existing JMS-heavy systems.

Which broker's storage model is based on an asynchronous journal?
Artemis's codebase originated from...

13. How can you optimize ActiveMQ broker performance?

Several concrete levers help ActiveMQ handle more load without adding hardware:

  • Lower the consumer prefetch limit for slow consumers so one client can't hoard a large batch of messages.
  • Use asyncSend for messages that don't need a synchronous broker round-trip.
  • Prefer KahaDB over JDBC persistence for local disk speed unless shared storage is required.
  • Split high-volume non-persistent traffic onto separate connectors/destinations from critical persistent traffic.
  • Tune the JVM heap and use the NIO transport for many concurrent connections.

It also helps to right-size the number of consumer threads relative to available CPU cores, since too many competing consumer threads can cause contention rather than added throughput. Monitoring the destination's memory usage percentage in the web console over time helps catch a slow-building backlog before it triggers flow control, and periodically reviewing KahaDB's data log file count can reveal whether cleanup is failing to keep pace with incoming persistent traffic, which itself can quietly degrade performance over weeks.

What does lowering the prefetch limit help with?
Which persistence option is typically faster for local, single-broker storage?

14. What is the difference between point-to-point and publish-subscribe messaging?

Point-to-point delivers each message to a single consumer pulled from a shared pool, well suited for distributing units of work like image-resize jobs across a worker fleet. Publish-subscribe delivers each message to every interested subscriber, well suited for notifying multiple unrelated systems about the same event - for example, an order-placed event that both a billing service and a shipping service need to react to independently.

The key structural difference is coupling: point-to-point couples message throughput to worker capacity, so you add workers to process faster, while publish-subscribe couples message volume to the number of interested subscribers, since each new subscriber gets its own full copy of the stream regardless of how many workers exist per subscriber.

A useful mental shortcut in interviews: if the answer to 'how many systems need this message' is 'exactly one, whichever is free next,' reach for point-to-point; if the answer is 'every system that cares about this kind of event,' reach for publish-subscribe.

Point-to-point messaging is best suited for...
In publish-subscribe, adding a new subscriber...

15. How do you troubleshoot slow consumers in ActiveMQ?

Start with the web console or JMX to check the queue's pending message count and consumer count - a steadily growing backlog with an active consumer usually means the consumer's processing logic, not the broker, is the bottleneck.

Check the prefetch limit: a high prefetch can let one consumer hold a large local batch of messages while barely working through them, starving other consumers on the same queue. Look at consumer-side logs and thread dumps for blocking calls, like slow database queries or external API timeouts, inside the message listener. If the slowness is intermittent, correlate it with GC pauses on the consumer JVM. Once diagnosed, fixes usually involve lowering prefetch, adding more consumer instances, moving heavy work off the listener thread into an async pool, or splitting the queue by message type so slow and fast work don't share the same backlog.

It also helps to rule out network-level causes, like a saturated link between broker and consumer host, before assuming the bottleneck is purely application code.

A growing backlog with an active consumer usually points to...
What can a high prefetch limit cause?
«
»

Comments & Discussions