Skip to main content

Elastic Email to AWS SES Migration

Migrating from Elastic Email to AWS SES

Elastic Email is one of the lowest-priced multi-purpose email platforms — transactional API, marketing builder, contact lists, and automation in a single product. AWS SES is a focused infrastructure primitive that costs less per message and gives you full control over reputation, IP isolation, and event tooling. The step-by-step migration plan — including the parts that are not obvious if you used the marketing builder, the automation flows, or the contact list manager.

Ask AI: ChatGPT Claude Perplexity Gemini

TL;DR. If you are migrating only transactional, plan 1–2 weeks on the SES side. If you are also moving the marketing builder, contact lists, and automation flows, plan 4–6 weeks plus a marketing-platform decision (own the builder in code, or pair SES with a marketing-only tool like Customer.io or Klaviyo).

Elastic Email occupies a different niche than SendGrid, Mailgun, or Postmark. It is a multi-purpose platform — transactional API, marketing builder, contact manager, automation engine, and SMTP relay all bundled together — priced aggressively at the low end and aimed at small-to-medium businesses that want one tool for every email job. AWS SES is the opposite: a focused, API-only sending primitive priced at infrastructure cost. The migration between them is therefore not just a credentials swap. It is a decision about how much of the email stack you want to own in code versus consume as a managed product.

This guide is for the engineering lead running that decision and the platform team executing it.

Where Elastic Email and SES Sit in the Market

Elastic Email started as a low-cost SMTP relay and has expanded over the years into a marketing-suite competitor. The product surface today includes:

The breadth is part of the appeal for teams that want one bill, one login, and one vendor. The breadth is also why migration is more involved than it looks — each capability you used has to be replaced, replicated, or retired.

AWS SES is a single-purpose service: send mail, receive mail, surface events. There is no UI for non-engineers, no marketing builder, no contact list, no automation engine. Anything beyond raw send-and-event capability is something you build, integrate, or replace with another tool.

The Pricing Comparison Is Plan-Specific

Elastic Email’s pricing fragments across product surfaces, which makes the comparison less direct than other ESPs.

Email API (transactional / SMTP relay):

VolumeElastic Email Email APIAWS SESMonthly Difference
10,000 emails$9/month (Pay-as-you-go)$1.00/month$8.00 SES savings
50,000 emails$40/month (volume tier)$5.00/month$35.00 SES savings
100,000 emails$75/month (volume tier)$10.00/month$65.00 SES savings
500,000 emails~$250/month$50.00/month$200.00 SES savings
1,000,000 emails~$450/month$100.00/month$350.00 SES savings

Marketing plans (builder + contacts + automation):

Plan tierElastic Email MarketingEquivalent on AWS
Up to 10,000 contacts, ~50K sends/month$15–25/monthSES $5/month + DynamoDB pennies + Step Functions free tier — but engineering build required
50,000 contacts, ~250K sends/month$75–120/monthSES $25/month + small DynamoDB cost + custom builder UI
100,000+ contacts, automation flows$200+/monthSES + Step Functions + custom contact admin UI

The Email API comparison is straightforward — SES wins on per-message cost at every tier. The Marketing comparison is not a direct cost question; it is a build-versus-buy question. Elastic Email Marketing bundles a product surface (the visual builder, the contact admin, the campaign reports) that has no SES equivalent. The honest framing for the marketing side is: how much engineering investment is your team willing to make to own that surface?

API Migration: Elastic Email REST → AWS SES

Elastic Email’s REST API is straightforward; the migration to SES is a conceptual remap rather than a major refactor.

Elastic Email APIAWS SES EquivalentNotes
POST /v4/emailsSendEmailCommand / SendBulkEmailCommandCore send operation
Recipients.To[]Destination.ToAddresses[]Direct field mapping
Content.From, Content.SubjectSource, Message.SubjectSame fields
Content.Body[] with ContentType: HTML/PlainTextMessage.Body.Html / Message.Body.TextBoth formats supported; SES requires explicit subobjects
MergeData[] (template variables)Application-rendered HTML or SES template variablesMove template rendering to app layer
Tracking.Open, Tracking.ClickConfiguration Set with tracking enabledSame capability, configured at the Configuration Set level
Tags[] (campaign tags)Configuration Set tags + MessageTag arrayFor event filtering and CloudWatch breakdowns
API key in X-ElasticEmail-ApiKey headerIAM credentials or SES SMTP credentialsPrefer IAM in production
SMTP (smtp.elasticemail.com, port 2525)email-smtp.[region].amazonaws.com, port 587Drop-in SMTP credential swap
POST /v4/emails/transactionalSame SendEmailCommand with transactional Configuration SetStream isolation in SES is per-Configuration Set

For teams using Elastic Email’s SMTP relay, the migration is a credentials swap. Update the SMTP host, port (SES uses 587 with STARTTLS or 465 with TLS), and credentials. No code changes. For teams using the REST API, the migration is a refactor of the send call and any helper code that depends on Elastic Email-specific JSON fields.

Templates: Elastic Email Builder → Code-Owned Templates

Elastic Email’s drag-and-drop builder produces HTML templates stored in the Elastic Email account. These templates use a proprietary merge-tag syntax ({merge_field}) and are managed through the UI. SES has no template builder — its template feature supports only basic {{variable}} substitution with no conditionals or layouts, and most teams skip the SES template feature entirely.

The recommended pattern is to move template rendering to your application code using one of three libraries:

Migration steps for an Elastic Email-builder template:

  1. Open the Elastic Email template in the builder. Export or copy the rendered HTML.
  2. Translate the merge-tag syntax ({first_name}{{firstName}} for Handlebars, or props.firstName for React Email).
  3. Re-test the rendered output across major email clients (Apple Mail, Gmail web, Outlook on Windows, Outlook for iOS). Outlook on Windows is the client most likely to break a builder-exported template because of its idiosyncratic CSS rendering.
  4. Add the template to version control next to the code that triggers it.

For organizations with a marketing team that cannot read code, splitting transactional (code-owned templates) from marketing (kept on a marketing-builder platform) is a defensible architecture. Customer.io, Loops, Bento, and Resend all maintain a builder UI while sending through SES under the hood — you get the cost benefit of SES on the marketing side without forcing marketing operations into a code-only workflow.

Contact Lists, Segments, and Subscriber Management

This is the largest hidden lift in the migration if you used Elastic Email’s marketing surface. Elastic Email’s contact and segment manager handles subscribe/unsubscribe state, custom fields, segment queries, and double-opt-in flows. SES has none of this.

The replacement architecture for an in-house contact store on AWS:

Migration data flow for an existing Elastic Email contact list:

  1. Export the contact list via Elastic Email’s REST API (GET /v4/contacts)
  2. Capture all custom fields, list memberships, and subscription status
  3. Bulk-load into DynamoDB with status preserved
  4. Add hard-bounced and complained addresses to the SES account-level suppression list via PutSuppressedDestination
  5. Cut over send code to read recipients from the new contact store

The engineering effort for the contact store, admin Lambda, and segment query layer is typically two to four weeks for one engineer. Add another two to four weeks if you need a marketing-team-friendly admin UI.

Automation Flows: Elastic Email Workflows → Step Functions + EventBridge

Elastic Email’s visual automation editor is the marketing surface most expensive to replace. There is no SES equivalent and no off-the-shelf AWS-native tool with the same drag-and-drop UX.

The native AWS pattern for replicating drip campaigns and behavior-triggered email flows:

Trigger source (signup, purchase, behavior event)

EventBridge custom event bus
  ↓ rule matches event pattern

Step Functions state machine (one per automation flow)
  ↓ Wait state (delay, e.g., "wait 3 days")
  ↓ Choice state (branch on contact status)
  ↓ Task state — invoke send Lambda

Lambda — render template, check suppression, call SES
SES → recipient

Key practices:

For teams without the engineering capacity to rebuild automation flows in Step Functions, splitting the architecture is sensible — keep automations on a marketing automation platform that integrates with SES (Customer.io, Loops, Beehiiv) and use SES directly only for transactional traffic.

Domain Verification, DKIM, DMARC, and the Authentication Stack

Elastic Email walks new customers through DKIM and SPF setup with a domain verification UI. SES asks for the same records but exposes more knobs. In 2026 — Gmail, Yahoo, and Microsoft now treat unauthenticated mail from any sender above 5,000 messages per day as effectively undeliverable — getting authentication right before the first production send is non-negotiable.

SPF. Add include:amazonses.com to your sending domain’s TXT record. If you keep Elastic Email running during the cutover window, your record looks like v=spf1 include:_spf.elasticemail.com include:amazonses.com -all until you fully cut over. Watch the 10-DNS-lookup limit; chained include: directives silently break SPF.

DKIM. Verify the domain in SES, enable Easy DKIM, and publish the three CNAME records SES generates. Easy DKIM rotates keys automatically. During parallel sending, Elastic Email’s DKIM selector and SES’s three CNAMEs coexist without conflict — both signatures validate independently because they use different selectors.

DMARC. Publish _dmarc.yourdomain.com with v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com from day one to start collecting aggregate reports. Move to p=quarantine after two to four weeks of clean reports, then to p=reject once every legitimate sender — transactional, marketing, calendar invites, vendor notifications, internal tooling — is aligned.

Custom MAIL FROM domain. Set up a custom MAIL FROM subdomain (e.g., mail.acme.com) and publish the SES-provided MX and SPF records for it. This makes SPF alignment with your visible From address explicit, which removes a class of subtle DMARC failures that surface only after p=reject enforcement.

BIMI. Once enforcement is stable and you have a Verified Mark Certificate from Entrust or DigiCert, publish a BIMI record so your logo renders next to messages in Gmail, Apple Mail, and Yahoo.

Common Elastic Email DNS cleanup mistakes after cutover:

Reputation: The Reset You Are Doing on Purpose

Elastic Email customers send from shared IP pools that include a wide range of senders. The reputation built on those IPs is not yours; it is the pool’s. After cutover, you start from zero on either the SES shared pool or your own dedicated IPs. For most senders this is good news — you trade an inherited reputation (whatever it was) for one you control.

Migrating to SES shared IPs. Suitable for transactional senders under 500,000 emails per month. There is no formal warming required, but mailbox providers still observe sending velocity per domain. Ramp gradually over 7–10 days rather than spiking from zero to full volume on day one.

Migrating to SES dedicated IPs. SES dedicated IPs cost $24.95 per IP per month — substantially cheaper than the dedicated-IP add-on on Elastic Email Pro plans. The trade-off is that you handle warming yourself.

Day RangeDaily Volume CapNotes
Days 1–3200 emails/daySend to most engaged segment only
Days 4–71,000 emails/dayWatch bounce rate (target <2%)
Days 8–1410,000 emails/dayAdd second engagement tier
Days 15–2150,000 emails/dayMonitor complaint rate (target <0.1%)
Days 22–30Full target volumeReputation established

Keep Elastic Email running in parallel for non-engaged segments during the warming window. The dual-vendor month is the cost of insurance against a deliverability dip that can take 60+ days to recover from.

List hygiene before cutover. This is the single highest-leverage activity in the migration. Elastic Email’s broader sender base means some senders on the shared pool ride looser hygiene than you would; don’t carry that habit into your own SES reputation.

Step-by-Step Migration Plan

A clean Elastic Email-to-SES cutover for a transactional product domain takes one to two weeks. A full migration including the marketing builder, contact lists, and automation flows is six to twelve weeks depending on the breadth of marketing surface in use.

Phase 1 — Inventory and decision (Week 1)

  1. Catalog every Elastic Email feature in active use — Email API, SMTP relay, marketing builder, contact lists, segments, automations, landing pages, verifications.
  2. Decide for each feature: migrate to AWS-native equivalent, replace with a third-party tool, or retire.
  3. The honest decision tree: transactional always migrates to SES; marketing builder either gets replaced with code-owned templates (engineering team) or stays on a marketing-specific platform (marketing team); automations either get rebuilt in Step Functions or stay on a marketing automation platform.

Phase 2 — Domain and SES setup (Week 1)

  1. Verify the sending domain in SES. Publish DKIM, SPF, DMARC, and custom MAIL FROM records. Leave Elastic Email records in place.
  2. Move out of the SES sandbox by submitting a production access request. Expect 24–48 hours.
  3. Create one Configuration Set per send category — transactional, notifications, marketing. Wire each to a Kinesis Firehose event destination writing to S3.

Phase 3 — Transactional code refactor (Week 1–2)

  1. Replace Elastic Email API client with AWS SDK SES client.
  2. Wrap every send site behind a sendEmail() helper that accepts a template, recipient, subject, category. Add a feature flag to route by category for phased rollout.
  3. Move template rendering to React Email, MJML, or Handlebars. Verify rendered output matches across major clients.
  4. Implement per-send checks: account-level suppression cache, frequency cap, idempotency key, quiet-hours preference.

Phase 4 — Event pipeline (Week 2)

  1. Subscribe each Configuration Set to Firehose; partition S3 by year/month/day/category.
  2. Build a small Lambda/Node.js API that queries Athena for activity logs, per-category metrics, bounce and complaint detail.
  3. Add CloudWatch alarms on bounce rate (>2%), complaint rate (>0.1%), send-rate anomalies (10x deviation from 7-day rolling average).

Phase 5 — Marketing surface (Week 3+, optional)

  1. Stand up the contact store (DynamoDB + admin Lambda) if you decided to rebuild internally. Otherwise, sign up for the marketing platform you chose and start the parallel migration.
  2. Migrate contact and list data via Elastic Email API export.
  3. Rebuild the highest-volume two or three automation flows in Step Functions. Lower-volume flows can be retired or rewritten later.
  4. Run a small broadcast (1,000 recipients) end-to-end to validate sending, tracking, and unsubscribe handling.

Phase 6 — Cutover and decommission (Final week)

  1. Flip the feature flag for transactional traffic. Keep Elastic Email running for 24–48 hours as fast rollback.
  2. Watch CloudWatch dashboards and Elastic Email reports in parallel. Investigate any divergence immediately.
  3. After 7 clean days, scale down Elastic Email plan, rotate API keys, remove Elastic Email’s SPF include from DNS.
  4. After 30 clean days, close the Elastic Email account.

Common Migration Challenges

Plan-tier confusion at export time. Elastic Email’s API access varies by plan. Pay-as-you-go and lower marketing tiers have rate limits on contact and event exports that make a same-day bulk migration impossible. Either upgrade temporarily for the export window or paginate exports across multiple days. Plan for this in the migration timeline.

Automation re-modeling. Automations built in Elastic Email’s visual editor often hide branching logic and time-based conditions that are not obvious from a screenshot. Document the full state machine of each automation before rebuilding. The most common failure mode is rebuilding the happy path and missing the “user unsubscribed mid-flow” edge case.

Unsubscribe link rewriting in evergreen automations. If a 30-day drip series has emails already in flight when you cut over, recipients receiving day-21 of the sequence may click an unsubscribe link that points to the old Elastic Email handler. Either keep Elastic Email’s unsubscribe handler live for 60+ days or pre-rewrite all in-flight sends to point to the new handler.

Mixed shared-pool reputation residue. If your domain’s previous reputation was poor on Elastic Email’s pool (high complaint rate, sustained list-quality issues), starting fresh on SES does not guarantee clean placement at major mailbox providers. Gmail and Outlook track reputation by sending domain across IPs. Fix list hygiene first; the IP change is downstream of the underlying reputation problem.

Apple MPP open inflation. Elastic Email’s reports already over-count opens because Apple Mail Privacy Protection prefetches every image. After migration to SES with raw event capture, the over-counting becomes more visible because you see every individual prefetch. Filter MPP opens (identifiable by the User-Agent: Mail/MPP and Apple-owned IP ranges) before feeding engagement data into segmentation logic.

SMTP port differences. Elastic Email defaults to port 2525 (and supports 25, 587, 465). SES SMTP uses 587 with STARTTLS or 465 with TLS. If your application allowed outbound port 2525 only, expand the egress rules before cutover.

Custom field mapping at template render time. Templates exported from the Elastic Email builder may use merge fields with names that do not match your code’s variable names. Build a translation layer in the sendEmail() helper that maps internal contact-record field names to the variable names templates expect.

Deliverability Discipline After the Cutover

SES does not paper over reputation problems. Three operational practices separate teams that maintain or improve placement after migration from teams that watch placement decay over six months.

Stream isolation through Configuration Sets and IP pools. Run separate Configuration Sets — and ideally separate dedicated IP pools — for transactional, product activity, and marketing traffic. A complaint spike on a marketing broadcast cannot reach password-reset deliverability if the IPs are isolated. Application code selects the correct Configuration Set per send category; tag every send with category for downstream filtering.

Engagement-based send eligibility. Maintain a last_engaged_at timestamp per recipient updated nightly from open and click events. Suppress recipients with no engagement in 90 days from marketing streams (180 days for transactional). Gmail and Microsoft weight recent positive engagement heavily. A smaller, hotter list lifts placement for the entire domain — typically from the mid-80s to the mid-90s within 30 days.

Per-domain placement testing. Send to a small panel of monitored seed inboxes (Gmail, Outlook, Yahoo, iCloud) on every major broadcast. Inbox vs. promotions vs. spam folder placement is your earliest warning system — much earlier than the bounce rate metric, which only spikes after reputation damage is already done.

Frequency caps and quiet hours. Build per-recipient frequency caps into the send Lambda — no more than N marketing emails per week, no transactional emails outside business hours unless the message is genuinely time-critical. Recipients who feel oversent unsubscribe; recipients who unsubscribe damage reputation for everyone else on your domain.

Production Event Pipeline: SES → Kinesis Firehose → S3 → Node.js API

Elastic Email’s hosted dashboard gives you per-email activity logs, basic charts, and campaign reports. After cutover you replicate that surface with the SES event firehose. The architecture most production SES senders converge on:

SES Configuration Set
   ↓ (event destination)
Kinesis Data Firehose
   ↓ (60-second buffer or 5 MB)
S3 (Parquet, partitioned by year/month/day/category)

Athena   ←  Node.js API   ←  Dashboard / suppression service / alerts

Subscribe each Configuration Set to a Firehose delivery stream. Enable dynamic partitioning so events split by category, sending IP, or recipient domain at write time. Lifecycle the bucket: Standard for 30 days (hot analytics window), Standard-IA at 30 days, Glacier Flexible Retrieval at 180 days. Raw events are the cheapest part of the stack and the most useful during deliverability investigations.

The Node.js API layer is small — a Fastify or Hono service, an Athena query helper, and four to six endpoints:

Filtering bot, prefetch, and security-scanner traffic. Apple MPP, Microsoft Defender link scanning, Gmail image proxies, and corporate security gateways all generate engagement events that have nothing to do with a human reading the message. Without filtering, your “open rate” double-counts machine activity and engagement-based suppression suppresses real subscribers whose mail clients prefetch links. Tools that score SES events for human vs. automated activity sit naturally between the Firehose stream and the Node.js API; teams that skip this layer often discover the gap only after a quarter of degraded marketing placement.

Explore other technical comparisons:

Why Choose FactualMinds for Your Email Migration

FactualMinds is an AWS Select Tier Consulting Partner specializing in email infrastructure migration. We have executed SendGrid, Mailgun, Postmark, SparkPost, Resend, and Elastic Email to AWS SES migrations and know exactly where teams get stuck.


Frequently Asked Questions

Is AWS SES cheaper than Elastic Email?
It depends on which Elastic Email product you use. Elastic Email's Email API plan starts around $0.09 per 1,000 emails on Pay-as-you-go (close to SES's $0.10) but adds platform fees and contact-storage charges as volume grows. The Marketing plans (with the drag-and-drop builder, contact lists, and automation) start at $15/month for unlimited contacts up to 10,000 sends and step up sharply. AWS SES is flat $0.10 per 1,000 messages with no platform fee, no contact-storage charge, and no plan tier — just per-message pricing. Once you cross 50,000 marketing emails per month or 200,000 transactional emails per month, SES is consistently cheaper end-to-end. The trade-off: SES has no marketing builder, no contact manager, and no automation engine; you replace those with application code or third-party tools.
Why do teams migrate off Elastic Email?
Three patterns dominate. First, deliverability — Elastic Email serves a wide spectrum of senders on shared IP pools, and reputation can be uneven across that pool. Teams that need predictable inbox placement (B2B SaaS transactional, regulated-industry notifications) often want their own reputation surface. Second, AWS-native consolidation — engineering teams running on AWS prefer IAM-based credentials, KMS encryption of suppression data, and CloudWatch metrics in one place. Third, scaling cost — Elastic Email is competitive at small volumes but becomes more expensive than SES once contact-storage fees, dedicated IP add-ons, and platform fees compound at scale.
How do I migrate Elastic Email automation flows to AWS?
Elastic Email automations (welcome series, drip campaigns, behavior-triggered sends) are built in their visual workflow editor and have no direct SES equivalent. The native AWS replacement is Step Functions for the orchestration layer, EventBridge for triggers (signups, behaviors, time delays), DynamoDB for contact state, and SES for the actual send. For teams without engineering bandwidth to build this, a hybrid is reasonable — keep marketing automation on a purpose-built tool like Customer.io or Loops while moving transactional traffic to SES. The migration is rarely a 1:1 export-import; flows must be re-modeled around the AWS event-driven primitives.
Will my deliverability improve after moving to AWS SES?
It depends on your current state. Senders with clean lists, strong authentication, and good engagement on Elastic Email's shared pool typically see neutral or slightly improved placement on SES because they get their own reputation surface and can isolate streams. Senders whose Elastic Email placement was suppressed by noisy neighbors on the shared pool often see meaningful improvement on SES dedicated IPs after a proper warm-up. Senders with poor list hygiene or weak authentication will see the same problems on SES — the platform does not paper over reputation issues. The migration is an opportunity to reset, but only if you fix the underlying hygiene at the same time.
Can AWS SES replace Elastic Email contact lists and segments?
There is no native equivalent. SES has no contact manager, no segments, no list builder, and no template-based marketing UI. You build the contact and segmentation layer yourself: DynamoDB or RDS for the contact store, application code for segment queries, and Step Functions or EventBridge Scheduler for triggered sends. For organizations that have heavy marketing-team usage of the Elastic Email contact builder, an honest assessment is whether transactional-only migration to SES (leaving marketing on Elastic Email or moving it to a marketing-specific platform) is the right architecture. Splitting transactional and marketing across two providers is a common and defensible pattern.

Need Help Migrating to AWS SES?

FactualMinds is an AWS Select Tier Partner specializing in email infrastructure migration. We handle domain verification, Configuration Set architecture, bounce handling, IP warming, and cutover.