← Back to Case Studies
High-volume

Sending 1 Million Emails in 25 Minutes

High-Performance Mautic on AWS

1M
Emails sent
25 min
Total time
~40k
Emails per minute
52
Parallel workers
Project → The client

About the Project

This sits inside a larger multi-tenant SaaS platform, where each tenant runs a white-labeled Mautic instance. As volume grew, the default pipeline — emails sent one by one via SMTP — became a bottleneck. Campaigns with hundreds of thousands of recipients took hours or timed out. We had to rebuild sending from scratch.

Context
Multi-tenant white-label Mautic
Bottleneck
One-by-one SMTP sending
Target
1M personalized emails in 25 min

Performance Results

Emails sent 1,000,000
Time 25 minutes
Throughput ~40,000 emails/minute
Workers ~52 parallel consumers
Batch size 1,000 per Mailgun API call
Queue stages 2
Stage 1 duration Seconds
Personalization Per-recipient dynamic content
Brief → Constraints

The Challenge

A production-scale pipeline had to solve volume, personalization, deliverability, and cost at the same time.

01

Send 1M+ emails in under 30 minutes

02

Personalize dynamic content per recipient

03

Keep deliverability at high volume

04

Work around AWS SQS 256KB message limits

05

Route bounces across multiple tenants

06

Run cost-efficiently on spot instances

Approach → Pipeline

The Solution

We replaced Mautic's default one-by-one SMTP sending with a three-stage parallel pipeline designed for throughput.

Architecture
Three-stage parallel pipeline
Workers
52 pods assembling payloads
Dispatch
Mailgun batch API, 1,000 per call
01

Segment Scanning

Mautic scans the campaign segment and batches millions of contacts into queue messages. This stage completes in milliseconds to seconds regardless of segment size, thanks to optimized database queries that only extract contact IDs.

02

Payload Assembly

52 parallel worker pods consume messages from the queue. Each worker assembles the full email payload: resolving dynamic content, personalizing templates per recipient, and batching up to 1,000 recipients per Mailgun API call.

03

Mailgun Batch API

Assembled batches are dispatched to Mailgun's batch API endpoint. Each API call handles up to 1,000 recipients with per-recipient variable substitution, eliminating the need for individual SMTP connections.

Engineering → Hard problems

Engineering Challenges

Volume was the brief. These are the constraints that actually shaped the pipeline.

01 Custom SQS + S3 Transport

AWS SQS has a 256KB message size limit. Email payloads with personalized HTML content easily exceed this. We built a custom transport layer: the full payload is stored in S3, and the SQS message contains only a reference to the S3 object. Workers fetch the payload from S3 on consumption. This eliminates the size constraint while maintaining queue reliability.

02 Intelligent Bounce Handling

With hundreds of tenants sharing a Mailgun domain, bounce notifications needed routing to the correct tenant instance. We implemented a custom header injection system: each outgoing email carries a tenant identifier header. A polling-based bounce processor reads Mailgun's event stream, extracts the tenant ID, and routes the bounce to the correct Mautic instance for contact status updates.

03 Graceful Processing Under Spot Interruptions

Worker pods run on spot instances for cost savings, but AWS can reclaim these with 2 minutes notice. We implemented graceful shutdown handling: when a termination signal arrives, workers stop consuming new messages, finish processing their current batch, and write checkpoints. A force-kill fallback ensures no orphaned processes. Messages from interrupted workers return to the queue automatically.

04 Email Deduplication & Queue Priority

With 52 parallel workers and thousands of queue messages, preventing duplicate sends is critical. We implemented a Redis-based deduplication layer that tracks processed contact IDs across all workers in real-time. Queue priority ensures time-sensitive campaigns are processed before bulk sends.

1,000,000

Emails in 25 minutes

40,000

Emails per minute

52

Parallel workers

0

Emails lost

Results → Outcomes

Business Impact

# Outcome What changed
01 Cost

Lower infrastructure cost than projected, thanks to spot instances.

02 Deliverability

API-based sending with reputation management kept inbox placement intact.

03 Reliability

Zero email loss during spot interruptions.

04 Reuse

SQS + S3 transport pattern reusable across the platform.

05 Scale

Ready for 300–500 tenants sending at once.

Stack → What we used

Tech Stack

Layer Tools
Email Delivery
Mailgun Batch API
Queue
AWS SQS S3 transport
Application
PHP Symfony Mautic
Storage
S3 FSx for Lustre
Orchestration
Kubernetes (EKS) Karpenter
Infrastructure
Spot instances Terraform
Monitoring
Grafana Prometheus Loki
Next step → Let's talk

Have a Similar Challenge?

Let's discuss your project. Free 30-minute consultation with a Mautic expert.

Talk to an Expert