ActiveMQ Container
Java Messaging Service for Commerce integrations.
Prerequisites
The activemq container image must be built and available. For information on building container images, see Building Container Images.
Suitable Environment Types
ActiveMQ is a required component for Self-Managed Commerce. The containerized ActiveMQ implementation can be suitable for all types of Self-Managed Commerce environments, including production, provided that a suitable persistent volume is used.
| Include in Development and QA Environments? | Include in Authoring Environments? | Include in Live Environments? |
|---|---|---|
| Yes | Yes | Yes |
Other ActiveMQ implementations can be used in place of the provided containerized implementation. For information about supported message broker options, see Supported Technologies.
Configuration
The sections below describe typical configurations.
Container user
The ActiveMQ container image is built to be run as user app_runner (user ID 10001), with user group app_runner (group ID 10001). Ensure that you specify the correct user and group when you run the container. Volumes should also be readable and writeable by this user. Consult your container orchestration documentation for more information.
tip
Below is an example security context snippet for a Kubernetes deployment.yaml file.
securityContext:
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
Note about production sizing and tuning
The values shared in this document are suggestions that are known to work well in typical scenarios.
Resource allocation
Resource allocation can vary by usage and load. Below are typical values.
| Resource | Non Production | Production Like (See Note) |
|---|---|---|
| Container Memory (MB) | 1280 | 1280 |
| Container Cores | 1 | 1 |
Scaling and replicas
ActiveMQ cannot be horizontally scaled.
| Configuration | Non Production | Production Like (See Note) |
|---|---|---|
| Minimum Replicas | 1 | 1 |
| Maximum Replicas | 1 | 1 |
Ports
| Port | Non Production | Production | Purpose | Comment |
|---|---|---|---|---|
| 61616 | Yes | Yes | Java Messaging Service (JMS). | This port should only be exposed internally, ideally only to the Commerce services. |
| 8161 | Yes | Yes | ActiveMQ administration tool. | This port should only be exposed internally, ideally only to development or operations users with a suitable business need. |
Health, Liveness and Readiness
You can use a TCP socket connection on either of the TCP ports, to validate the availability of ActiveMQ.
Volumes
| Mount Point | Purpose | Comment |
|---|---|---|
| /ep/efs | Persist unprocessed JMS messages. | This volume holds the KahaDB message store and must meet the requirements described in KahaDB Mount. The efs in the mount path is historical and does not mean the volume should be EFS-backed; EFS is not appropriate for this store. A recommended size for this volume is 100GB. |
KahaDB Mount
ActiveMQ persists messages in a KahaDB message store on the /ep/efs volume. The /ep/efs mount path is a historical name and is not a recommendation to use EFS: EFS, like other shared filesystems, is not appropriate for the KahaDB store (see Single-writer block storage below). The path is hard-coded in the ActiveMQ image configuration and stays the same regardless of what storage backs the volume; back it with ReadWriteOnce block storage as described here. KahaDB is a file-based journal, and its integrity depends on specific capabilities of the underlying storage. Using an unsuitable volume can result in journal corruption, message loss, and a broker that fails to start. The volume backing the KahaDB store must meet all of the following requirements.
Persistence
The volume must outlive the container. If an ActiveMQ instance dies and a new instance replaces it, on the same host or a different one, the new instance must find the existing message store so that unprocessed messages can be recovered and processed. In Kubernetes and OpenShift, this means the message store must be on a persistent volume whose lifecycle is independent of the pod and of routine redeployments. Create the PersistentVolumeClaim once and treat it as stateful infrastructure: do not recreate it as part of deployment automation. If the claim is managed by Helm, annotate it with "helm.sh/resource-policy": keep to prevent it from being deleted on upgrade or uninstall.
Single-writer block storage (ReadWriteOnce)
The volume must be network-attached block storage with the ReadWriteOnce access mode, so that it can only be attached to one node at a time. Examples include AWS EBS, Azure Disk, Google Compute Engine persistent disks, and Ceph RBD (for example, the ocs-storagecluster-ceph-rbd storage class provided by OpenShift Data Foundation).
Do not place the KahaDB store on a shared filesystem or ReadWriteMany volume, such as NFS, AWS EFS, Azure Files, or CephFS. On a shared filesystem, the only protection against two brokers writing the same journal is the KahaDB file lock, and the advisory, lease-based locking that shared filesystems provide can fail when a pod is force-killed, a node is drained, or a node loses contact with the control plane while the old broker keeps running. If two brokers ever write the journal concurrently, the store is corrupted. ReadWriteOnce block storage makes this failure mode physically impossible, because the volume cannot attach to a second node.
Network-attached block storage also satisfies the persistence requirement above: the volume detaches from a failed node and reattaches wherever the replacement pod is scheduled, with all data intact. Availability across hosts does not require a shared filesystem.
Shared filesystems also cache and reorder writes across clients, which breaks the synchronous write (fsync) guarantees that KahaDB depends on for crash recovery. This can leave torn or partial records in the journal even without concurrent writers.
Single broker instance
Only one ActiveMQ instance may use the message store at a time. In a Kubernetes or OpenShift Deployment:
- Set
replicas: 1explicitly. Do not template the replica count in a way that allows it to be increased; a second replica pointed at the same store is not a valid high-availability configuration. - Set the update strategy to
Recreaterather than the defaultRollingUpdate, so that the old pod fully stops before the new pod starts. WithRollingUpdate, every redeployment briefly runs two brokers. - Set
terminationGracePeriodSecondshigh enough for a clean broker shutdown (for example,180). The Kubernetes default of 30 seconds can force-kill the broker mid-write, causing an unclean shutdown.
spec:
replicas: 1
strategy:
type: Recreate
template:
spec:
terminationGracePeriodSeconds: 180
Capacity headroom
KahaDB can corrupt its journal if a write fails because the volume is full. Protect against this in two ways:
- In
activemq.xml, set thestoreUsagelimit in thesystemUsageelement to roughly 70-80% of the volume size. When the limit is reached, the broker applies producer flow control instead of writing until the disk is full. - Monitor volume utilization and queue depths, including the dead-letter queue (
ActiveMQ.DLQ). Sustained growth of the message store usually means a consumer has stopped processing; KahaDB cannot clean up a journal file while any message in it remains unconsumed.
important
A ReadWriteMany volume on NFS, EFS, Azure Files, or CephFS is the most common cause of KahaDB corruption in containerized deployments. If your ActiveMQ message store is currently on a shared filesystem, plan a migration to ReadWriteOnce block storage: create a new claim, stop the broker, copy the kahadb directory to the new volume, and update the deployment. Access mode and storage class cannot be changed on an existing PersistentVolumeClaim.
Environment Variables
Elastic Path's containerization tools have been updated to allow ActiveMQ to optionally be configured using container environment variables. The environment variables are read and consumed by the container entrypoint scripts.
The following table shows additional environment variables specific to the ActiveMQ container:
| Variable Name | Description | Required |
|---|---|---|
EP_CONTAINER_MEM_ACTIVEMQ | Used to set the Java heap size. Both the initial heap (Xms) and maximum heap (Xmx) are set to this value. | Yes |
EP_ACTIVEMQ_X_JVM_ARGS | Can be used to set additional custom Java command-line arguments. Values set in this environment variable are appended to the JDK_JAVA_OPTIONS variable, which is consumed by the Java virtual machine. | No |
MAXIMUM_CONNECTIONS | Can be used to modify the maximumConnections parameter in the ActiveMQ configuration file /ep/apache-activemq/conf/activemq.xml. This must be an integer, and defaults to 1000. | No |
important
The entrypoint scripts are and will remain the source of truth on the required environment variables. Review the container entrypoint scripts in your selected release to validate the required variables.