Magento 2 Email Performance Optimization: From SMTP Bottlenecks to Async Sending
Email is often the forgotten performance bottleneck in Magento 2. While stores obsess over page load times and database queries, the email subsystem quietly drags down checkout completion, order processing, and cron execution. A single slow SMTP handshake can add seconds to every order placement. Multiply that by hundreds of orders per hour and you have a real problem. In this post we'll diagnose the most common email performance issues and implement fixes that actually move the needle.
The Hidden Cost of Synchronous Email
By default, Magento 2 sends emails synchronously during the request lifecycle. When a customer places an order, the system:
- Renders the email template (PHP + HTML compilation)
- Opens an SMTP connection
- Authenticates and transmits the message
- Waits for server acknowledgement
- Closes the connection
Steps 2-4 happen inside the same request that renders the order success page. If your SMTP server is 150ms away and takes 300ms to accept a message, every customer waits an extra 300-500ms after clicking "Place Order."
During peak traffic this compounds into connection exhaustion and timeout errors. The worst part? These delays rarely show up in standard profiling because they're classified as "network I/O" rather than Magento code execution.
Fix 1: Enable Async Email Sending
Magento 2.4+ includes built-in support for asynchronous email via RabbitMQ or MySQL message queues. This decouples email transmission from the frontend request.
Enable it in app/etc/env.php:
'system' => [
'default' => [
'sales_email' => [
'general' => [
'async_sending' => 1
]
]
]
]
Or via CLI for immediate effect:
bin/magento config:set sales_email/general/async_sending 1
bin/magento cache:clean config
With async sending enabled, order confirmation emails are queued immediately and processed by a background consumer. The customer sees the success page instantly while the email ships separately.
Verify the consumer is running:
bin/magento queue:consumers:start sales.sendOrderEmails
For production, register this as a systemd service or Supervisord process. Without a running consumer, emails accumulate in the queue indefinitely.
Fix 2: SMTP Connection Pooling with External Providers
Default Magento uses PHP's mail() function or opens a fresh SMTP connection per email. Both are inefficient at scale.
Switch to a transactional email service (Mailgun, SendGrid, AWS SES, Postmark) and configure connection reuse. Most support HTTP APIs that are faster than SMTP handshakes, but if you must use SMTP, enable persistent connections.
For SendGrid via SMTP in app/etc/env.php:
'system' => [
'default' => [
'system' => [
'smtp' => [
'host' => 'smtp.sendgrid.net',
'port' => 587,
'auth' => 'login',
'username' => 'apikey',
'password' => 'SG.your-api-key-here',
'ssl' => 'tls'
]
]
]
]
Better yet, use a Magento module that calls HTTP APIs directly. HTTP requests have lower overhead than SMTP connection negotiation and support keep-alive pooling natively.
Fix 3: Template Compilation Cache
Email templates in Magento 2 are PHP-based and compiled at runtime. The first time a template renders, Magento parses the .html file, extracts directives (`{{var order.getIncrementId()
Comments
No comments yet. Start the discussion.