
ElasticMQ is an in-memory message queue system with an Amazon Simple Queue Service (SQS)-compatible interface. It provides a lightweight, fast alternative to AWS SQS for local development, testing, and production workloads where cloud dependency is undesirable. ElasticMQ supports standard and First-In-First-Out (FIFO) queues, dead-letter queues, message visibility timeouts, and optional persistence to survive restarts.
This article explains how to deploy ElasticMQ as a self-hosted alternative to AWS SQS. It covers a Docker-based installation, queue configuration, dead-letter queue setup, the web user interface (UI), message persistence, and migration strategies from AWS SQS.
AWS SQS is a fully managed message queue service tightly integrated with the AWS ecosystem. ElasticMQ offers SQS API compatibility with infrastructure independence and simplified deployment.
ElasticMQ maps directly to AWS SQS concepts.
The ElasticMQ architecture consists of:
elasticmq-ui container) for viewing queue statistics and message counts in real time.Before you begin, you need to:
ui.DOMAIN-NAME) pointing to the same server, for the Web UI. The UI application serves its static assets from absolute root paths, so it cannot share a path prefix on the same domain as the REST API.Docker provides the fastest path to a running ElasticMQ instance. The native image built with GraalVM starts in milliseconds and uses minimal memory. Traefik fronts the deployment as a reverse proxy and TLS terminator, obtaining a Let's Encrypt certificate for your domain. It routes to the ElasticMQ containers directly over the internal Docker network using labels.
Create the project directory with subdirectories for data persistence and TLS certificate storage.
data: Stores the H2 database files for message persistence.letsencrypt: Stores the Let's Encrypt certificate Traefik obtains for your domain.Switch to the project directory.
Create the ElasticMQ configuration file.
Add the following configuration to define the server settings and pre-create queues, replacing DOMAIN-NAME with the domain you pointed at your server in the Prerequisites section.
Save and close the file.
In this configuration:
node-address: Defines the external URL used in queue URLs returned by the API. Setting this to your domain over HTTPS ensures queue URLs work through the Traefik front end you configure next.rest-sqs: Configures the SQS-compatible API endpoint. bind-hostname stays at 0.0.0.0 so Traefik can reach the container over the internal Docker network.queues: Pre-creates queues at startup with specified attributes.aws: Sets the region and account ID used in queue URLs for SQS API compatibility.Generate a password hash to protect the Web UI with HTTP basic authentication, replacing UI-PASSWORD with a password of your choice.
The output is an apr1-hashed password string. Copy it for the next step.
Create an environment file to store your domains, Let's Encrypt contact email, and Web UI credentials.
Add the following content, replacing the placeholder values with your own:
Replace:
apr1 hash from the previous step, with every $ doubled (for example, $apr1$abc123 becomes $$apr1$$abc123). Docker Compose treats a single $ as a variable reference, including inside values loaded from .env. Replace DOMAIN-NAME with the same domain you used in elasticmq.conf, and ADMIN-EMAIL with your email address for Let's Encrypt certificate notifications.
Save and close the file.
Create the Docker Compose file.
Add the following configuration.
Save and close the file.
This manifest defines:
traefik: Terminates HTTPS for both domains and automatically obtains a Let's Encrypt certificate for each using the TLS-ALPN-01 challenge. HTTP traffic on port 80 redirects to HTTPS. The Docker socket mount lets Traefik discover the elasticmq and elasticmq-ui containers and their routing labels.elasticmq: Runs the SQS-compatible REST API. Its Traefik labels route all requests for DOMAIN to port 9324 inside the container. No host port is published, since Traefik reaches the container over the internal elasticmq Docker network.elasticmq-ui: Runs the web UI on its own subdomain, UI_DOMAIN, protected by a Traefik basicauth middleware so only credentialed requests reach it. The UI application's static assets also load from absolute root paths, so it needs a dedicated domain rather than a path prefix on the same domain as the REST API.networks: The internal elasticmq network lets Traefik reach both containers by name without exposing them to the host or the internet.Start the ElasticMQ and Traefik containers.
Verify the containers are running.
The output displays three running containers: traefik, elasticmq, and elasticmq-ui.
Check the Traefik logs to confirm it obtained a certificate for your domain.
The output includes an INF line reading Register... for myresolver.acme, with no ERR lines. This confirms Traefik requested a certificate from Let's Encrypt without errors.
For more information on managing a Docker Compose stack, see the How To Use Docker Compose article.
ElasticMQ queues can be pre-configured at startup or created dynamically using the SQS API. Pre-configuration ensures queues exist immediately when the server starts.
Open the configuration file.
Locate the existing queues section and add your queue definitions. The following example adds three queues alongside the existing default-queue:
Save and close the file.
In this configuration:
defaultVisibilityTimeout: Time in seconds a message is hidden after being received. If not deleted within this time, the message becomes visible again.delay: Time in seconds before new messages become available for consumption.receiveMessageWait: Maximum time in seconds to wait for messages when using long polling.Restart ElasticMQ to apply the changes.
Dead-letter queues (DLQs) capture messages that fail processing after a specified number of attempts. This prevents problematic messages from blocking the main queue while preserving them for analysis.
Open the configuration file.
Locate the queue you want to configure with a dead-letter queue (for example, orders-queue) and add the deadLettersQueue block. Also add the DLQ itself as a separate queue:
Save and close the file.
In this configuration:
deadLettersQueue.name: The queue that receives failed messages.deadLettersQueue.maxReceiveCount: Number of receive attempts before moving the message to the DLQ. Valid values are 1 to 1000.Restart ElasticMQ to apply the changes.
The ElasticMQ Web UI runs as a separate container, reachable on its own subdomain through Traefik.
Open a web browser and navigate to https://UI-DOMAIN-NAME, replacing UI-DOMAIN-NAME with the UI subdomain from the Prerequisites section.
Enter the UI-USERNAME and password you set in the Docker Compose configuration when the browser prompts for HTTP basic authentication.
The dashboard displays all configured queues with their current message counts, including messages available, messages in flight, and messages delayed.
Click a queue name to view detailed statistics and send or receive test messages.
By default, ElasticMQ stores all data in memory, meaning queues and messages are lost on restart. Enable persistence to retain data across restarts using an H2 database.
Open the configuration file.
Add the following messages-storage section at the end of the file.
Save and close the file.
Restart ElasticMQ to apply the changes.
ElasticMQ now persists all queues and messages to an H2 database file. On restart, the previous state is automatically restored.
Validate the full request path, from the AWS CLI through the TLS front end to ElasticMQ, by testing queue operations with the AWS CLI against your domain over HTTPS.
Download the AWS CLI installer.
Extract the installer archive.
Run the installer.
Configure the AWS CLI with placeholder credentials. ElasticMQ accepts any credentials.
Enter the following when prompted:
testtestus-east-1jsonConfirm the domain serves a valid TLS certificate, replacing DOMAIN-NAME with your domain.
The output shows HTTP/2 400. This status comes from ElasticMQ itself, which rejects a bare request with no SQS action, confirming the TLS handshake succeeded and the request reached ElasticMQ through the front end.
Confirm the Web UI rejects requests without credentials, replacing UI-DOMAIN-NAME with your UI subdomain.
The output shows HTTP/2 401, confirming the Traefik basicauth middleware is active.
Confirm the Web UI accepts the credentials you configured, replacing UI-DOMAIN-NAME, UI-USERNAME, and UI-PASSWORD with your values.
The output shows HTTP/2 200.
Create a test queue, replacing DOMAIN-NAME with your domain.
The output displays the queue URL.
Send a test message.
The output shows the message ID and MD5 hash.
Receive the message.
The output displays the message body and receipt handle.
Delete the message using the receipt handle from the previous output. Replace RECEIPT-HANDLE with the actual value.
List all queues to verify the deployment.
The output displays all configured queues including the test-queue created earlier.
Migrating from AWS SQS to ElasticMQ means recreating queue configurations and repointing application endpoints, since ElasticMQ implements the SQS API. Consult the current AWS SQS documentation and the ElasticMQ documentation for exact commands and options when you plan your migration.
Recreate your existing AWS SQS queue definitions in ElasticMQ. List the queues in your AWS account with aws sqs list-queues, and retrieve each queue's configuration with aws sqs get-queue-attributes using the --attribute-names All option. Map the AWS attributes to their ElasticMQ configuration keys, then add the queue definitions to the ElasticMQ configuration file as described in the Configure ElasticMQ Queues section.
The AWS attributes map to ElasticMQ configuration as follows:
VisibilityTimeout maps to defaultVisibilityTimeoutDelaySeconds maps to delayReceiveMessageWaitTimeSeconds maps to receiveMessageWaitRedrivePolicy maps to deadLettersQueueElasticMQ supports FIFO queues with message deduplication. Define a FIFO queue by adding the .fifo suffix to the queue name and setting fifo = true in the queue's configuration block, along with contentBasedDeduplication = true to deduplicate messages by content hash. FIFO queues support message group IDs for ordered processing within groups, and deduplication using either content-based hashing or explicit deduplication IDs.
Configure dead-letter queues in ElasticMQ to match your AWS SQS redrive policies. For each queue with a redrive policy in AWS, create a corresponding DLQ in ElasticMQ and set the maxReceiveCount to match your AWS maxReceiveCount value.
ElasticMQ is best suited for development, testing, continuous integration (CI), and controlled self-hosted environments. For production systems, validate durability, authentication, monitoring, and availability requirements before replacing AWS SQS.
For queues with existing messages that need preservation:
Drain existing messages: Process all messages in AWS SQS before switching to ElasticMQ.
Dual-write period: Configure producers to send messages to both AWS SQS and ElasticMQ during the migration window.
Cutover: Once consumers are migrated and the AWS queues are empty, disable the AWS SQS producers.
Update application code to target the ElasticMQ endpoint instead of AWS SQS. Because ElasticMQ implements the SQS query API, AWS SDK clients typically need only an endpoint change. Point the SDK client at the ElasticMQ endpoint (for example, set the boto3 client's endpoint_url to http://SERVER-IP:9324), specify the region, and provide placeholder credentials, since ElasticMQ accepts any values. For applications or frameworks that read endpoint configuration from environment variables, set AWS_ENDPOINT_URL, AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY accordingly.
sqs-limits = strict.receiveMessageWait. Configure this to reduce empty responses and API calls.ufw allow from CLIENT-IP to any port 443 proto tcp, or create an equivalent Vultr Cloud Firewall group and attach it to the server.You have deployed ElasticMQ as a self-hosted alternative to AWS SQS, fronted by Traefik with automatic HTTPS. This article covered Docker-based installation, TLS termination for a public domain, queue configuration with visibility timeouts and delays, dead-letter queue setup for failed message handling, the web UI for monitoring, message persistence using H2 database, and migration strategies from AWS SQS. ElasticMQ provides a lightweight, SQS-compatible message queue suitable for development, testing, and production workloads. For additional configuration options and advanced features, visit the official ElasticMQ documentation.
0 Comments
Be the first to comment and share your perspective with the community.