Back to Blog

Mautic Email Queue Optimization: From 1 Email/Minute to 40,000/Minute

M
Mautomic Team
8 min read

"12k emails in queue. Only processing one per minute."

This exact complaint appears on the Mautic forum every few weeks. And if you've ever watched Mautic crawl through a campaign send while your marketing team asks why the emails haven't gone out yet, you know the feeling.

The default Mautic installation is not configured for volume. Out of the box, it processes emails sequentially, uses conservative batch limits, and runs a single queue worker. For a list of 500 contacts, that's fine. For 50,000 or 500,000, it's a problem.

The good news: this is a solvable engineering problem. We've taken Mautic from the "one email per minute" situation all the way to 40,000 emails per minute - 1 million personalized emails in 25 minutes. Here's every optimization along the way, from the 15-minute quick wins to the full production architecture.

Why Mautic's Default Email Sending is Slow

Before fixing anything, it helps to understand where the bottleneck actually is.

Mautic processes outbound email through the Symfony Messenger component (since Mautic 5). When you trigger a campaign or broadcast, Mautic doesn't send emails immediately. It queues messages, and a background worker (messenger:consume) picks them up and processes them.

The problem is that the default setup has several compounding bottlenecks:

1. Single worker, low batch limit. The default cron runs one messenger:consume process with a small --limit (often 50 messages). Process 50, stop, wait for cron to fire again. With a 1-minute cron interval, that's 50 emails/minute at best.

2. SMTP sends one-by-one. If you're using SMTP transport (the most common setup), Mautic opens a connection, sends one email, closes the connection. Repeat. Each cycle takes 200-500ms depending on network latency to your SMTP server. That's a hard ceiling of ~2-5 emails/second regardless of anything else.

3. Database contention. Every email send triggers multiple database writes - updating email_stats, lead_event_log, and campaign_lead_event_log. On a single MySQL server with default configuration, these writes compete with the web UI and segment recalculations.

4. No parallel processing. Out of the box, there is exactly one process consuming the queue. One. For an application that might need to send hundreds of thousands of emails.

Now let's fix each layer.

Quick Wins (15 Minutes)

These changes require no architectural changes - just configuration updates.

Increase the batch limit

The biggest immediate improvement. Edit your cron job to increase --limit:

bash
# Before (default): processes 50 messages per run
* * * * * php /var/www/mautic/bin/console messenger:consume async --limit=50 --time-limit=60

# After: processes 500 messages per run
* * * * * php /var/www/mautic/bin/console messenger:consume async --limit=500 --time-limit=55

The --time-limit=55 ensures the process exits before the next cron minute, preventing overlap. This alone can take you from 50/minute to 500/minute - a 10x improvement for zero cost.

Prevent cron overlap with flock

If a previous run hasn't finished when the next cron fires, you get two workers fighting over the same queue. Use flock:

bash
* * * * * flock --timeout=55 /tmp/mautic-messenger.lock php /var/www/mautic/bin/console messenger:consume async --limit=500 --time-limit=55

This ensures only one instance runs at a time. Simple, but prevents a class of problems that cause duplicate sends and database deadlocks.

Switch from SMTP to API transport

This is the single highest-impact change for most installations.

SMTP sends emails synchronously, one at a time, over a TCP connection. API-based transports (SendGrid API, Amazon SES API) accept emails over HTTP and handle delivery asynchronously. The difference is dramatic:

  • SMTP to SendGrid: ~2-5 emails/second (limited by connection overhead)
  • SendGrid API: ~50-100 emails/second per worker (HTTP POST, batch-capable)

In your Mautic local.php or .env:

php
// .env.local for Mautic 5+
MAILER_DSN=sendgrid+api://YOUR_API_KEY@default

Or for Amazon SES:

php
MAILER_DSN=ses+api://ACCESS_KEY:SECRET_KEY@default?region=eu-west-1

If you're using SMTP and wondering why emails are slow, this is probably why.

Basic database tuning

Mautic is database-heavy. These MySQL/MariaDB settings make a meaningful difference:

ini
# /etc/mysql/conf.d/mautic.cnf
[mysqld]
innodb_buffer_pool_size = 2G          # Set to ~70% of available RAM
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2    # Trade tiny durability risk for speed
innodb_flush_method = O_DIRECT
max_connections = 200

Restart MySQL after changes. The innodb_buffer_pool_size alone can significantly reduce query times if your dataset fits in memory.

Expected result after quick wins: 500-2,000 emails/minute depending on your server specs and email delivery provider.

Medium Optimizations (1-2 Hours)

These require some infrastructure work but are still within reach for a team with basic DevOps capability.

Run multiple queue workers

This is the biggest unlock at the medium level. Instead of one messenger:consume process, run several in parallel.

Using systemd (recommended for production):

ini
# /etc/systemd/system/[email protected]
[Unit]
Description=Mautic Queue Worker %i
After=network.target mysql.service

[Service]
User=www-data
WorkingDirectory=/var/www/mautic
ExecStart=/usr/bin/php bin/console messenger:consume async --limit=200 --time-limit=3600 --memory-limit=256M
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Then start multiple instances:

bash
# Start 4 parallel workers
sudo systemctl enable mautic-worker@{1..4}
sudo systemctl start mautic-worker@{1..4}

# Check status
sudo systemctl status mautic-worker@*

With 4 workers and API transport, you're looking at 4x the throughput of a single worker. The limit here is your database and email provider, not Mautic itself.

Important: Don't remove the cron-based messenger:consume until you've confirmed systemd workers are running. And don't go above 4-6 workers without also addressing database capacity - the writes will become the bottleneck.

Move to Redis for cache and sessions

By default, Mautic uses filesystem caching. Under parallel worker load, this causes lock contention. Redis eliminates this:

php
// config/local.php
$parameters = [
    'cache_adapter' => 'cache.adapter.redis',
    'cache_prefix'  => 'mautic_',
    'cache_lifetime' => 86400,
];

And in .env.local:

bash
REDIS_URL=redis://localhost:6379

Redis also enables faster session handling if you're running Mautic behind a load balancer.

Add database indexes

Mautic's default schema is missing some indexes that matter at scale. These queries are the ones that slow down as your email_stats and event log tables grow:

sql
-- Speed up email stat lookups
CREATE INDEX idx_email_stats_email_id_date 
ON email_stats (email_id, date_sent);

-- Speed up campaign event log queries
CREATE INDEX idx_campaign_lead_event_log_campaign_date 
ON campaign_lead_event_log (campaign_id, date_triggered);

-- Speed up lead event log cleanup
CREATE INDEX idx_lead_event_log_date 
ON lead_event_log (date_added);

Run these during a maintenance window. On large tables (millions of rows), index creation can take minutes and temporarily lock the table.

Purge old data

This is often overlooked. If your email_stats table has 50 million rows from 2 years of campaigns, every query touching that table is slower than it needs to be.

bash
# Mautic 5+ has a built-in cleanup command
php bin/console mautic:maintenance:cleanup --days-old=180 --dry-run

# If the numbers look right, run for real
php bin/console mautic:maintenance:cleanup --days-old=180

We've seen tables go from 200GB+ to under 10GB after cleanup, with immediate performance improvements across the board.

Expected result after medium optimizations: 5,000-10,000 emails/minute with 4-6 workers and API transport.

Advanced Architecture: What 40,000 Emails/Minute Looks Like

The optimizations above will get most Mautic installations to a reasonable place. But if you need to send millions of emails per campaign reliably, the architecture needs to change more fundamentally.

Here's what we built for a client who needed to send 1 million personalized emails per campaign run:

Separate concerns

The single biggest architectural decision: don't run queue workers on the same server as the web UI.

text
                    +----------------+
                    |   Load         |
                    |   Balancer     |
                    +-------+--------+
                            |
               +------------+------------+
               |                         |
       +-------v-------+       +--------v--------+
       |  Web Server   |       |  Web Server     |
       |  (Mautic UI)  |       |  (Mautic UI)    |
       +-------+-------+       +--------+--------+
               |                         |
               +------------+------------+
                            |
                    +-------v--------+
                    |   Database     |
                    |   (Primary)    |---- Read Replica
                    +-------+--------+     (for reports)
                            |
               +------------+------------+
               |      Message Queue      |
               |    (Redis / RabbitMQ)   |
               +------------+------------+
                            |
          +---------+-------+-------+---------+
          |         |       |       |         |
       +--v--+  +--v--+ +--v--+ +--v--+  +--v--+
       | W1  |  | W2  | | ... | | W51 |  | W52 |
       +-----+  +-----+ +-----+ +-----+  +-----+
         52 parallel queue workers

The numbers

  • 52 parallel workers consuming from the message queue
  • RabbitMQ as the message broker (more reliable than Redis for this volume)
  • Dedicated database server with 64GB RAM, NVMe storage
  • Read replica serving all reporting/dashboard queries to keep the primary clean
  • SendGrid API with dedicated IPs for delivery

Result: ~40,000 emails/minute. 1 million personalized emails in 25 minutes. Deliverability stayed above 98%.

Why 52 workers?

Not arbitrary. We profiled and found that at ~50 workers, the database write throughput saturated. Adding more workers past that point actually reduced throughput due to connection contention and lock waits. The optimal number depends on your database server specs, email provider rate limits, and email personalization complexity.

What this requires

This level of architecture is not a weekend project. It requires:

  • Containerized deployment (Docker/Kubernetes)
  • Proper queue infrastructure (RabbitMQ or Redis Streams)
  • Database tuning for high write throughput
  • Monitoring and alerting (you need to know when workers die)
  • Capacity planning for email provider rate limits

When to DIY vs. Get Help

Here's an honest breakdown:

Quick wins (do it yourself): Anyone running Mautic can apply the cron tuning, switch to API transport, and adjust database settings. Budget an afternoon. Expected improvement: 10-50x over defaults.

Medium optimizations (needs a DevOps person): Running parallel workers with systemd, adding Redis, tuning indexes - this is standard infrastructure work. If you have someone comfortable with Linux administration, they can handle it. Budget 1-2 days.

Advanced architecture (this is what we do): Designing a parallel worker architecture, setting up proper message queuing, database read replicas, and monitoring for a high-volume Mautic deployment - this is where we come in. It's what we've built multiple times, and the difference between "sort of works" and "1 million emails in 25 minutes" is in the details that only come from doing it before.

Sending campaigns to 100K+ contacts and it takes hours? We've optimized Mautic to send 1 million emails in 25 minutes. Schedule a free 30-minute consultation to discuss your specific setup.

See the full case study: High-Performance Email Pipeline

M

Written by

Mautomic Team

The Mautomic team brings together experienced marketing automation specialists, developers, and consultants dedicated to helping businesses succeed with Mautic.

Need Help with Mautic?

Our team of experts is ready to help you implement and optimize your marketing automation.

Get in Touch