Migrate from AWS SES
SES gives you a raw sending primitive and leaves the rest — bounce handling via SNS, suppression lists, open and click tracking, configuration sets — for you to assemble and operate. Migrating to eusend mostly means deleting that assembly: the platform does those jobs out of the box. And where SES in eu-west-1 keeps your mail in an EU region of a US cloud, eusend is EU end-to-end — EU infrastructure, EU company.
The code change
Install the SDK with npm install @eusend_dev/sdk. The nested Destination/Content structure flattens into plain fields, and auth is an API key instead of IAM credentials. Calls return { data, error } instead of throwing.
import {
SESv2Client,
SendEmailCommand,
} from '@aws-sdk/client-sesv2'
const ses = new SESv2Client({ region: 'eu-west-1' })
await ses.send(new SendEmailCommand({
FromEmailAddress: 'Acme <hello@acme.com>',
Destination: { ToAddresses: ['user@example.com'] },
Content: {
Simple: {
Subject: { Data: 'Welcome' },
Body: {
Html: { Data: '<p>Thanks for signing up.</p>' },
},
},
},
}))import { Eusend } from '@eusend_dev/sdk'
const eusend = new Eusend(
process.env.EUSEND_API_KEY
)
await eusend.emails.send({
from: 'Acme <hello@acme.com>',
to: 'user@example.com',
subject: 'Welcome',
html: '<p>Thanks for signing up.</p>',
})Field mapping
| SES (SESv2) | eusend | Notes |
|---|---|---|
| FromEmailAddress | from | Must use a domain you verified in eusend |
| Destination.ToAddresses / CcAddresses / BccAddresses | to / cc / bcc | String or array |
| ReplyToAddresses | replyTo | — |
| Content.Simple.Subject.Data | subject | — |
| Content.Simple.Body.Html / Text | html / text | — |
| Content.Raw (SendRawEmailCommand) | headers | If you built raw MIME just to set custom headers, a plain headers object replaces it. For attachments, pass an attachments array (base64 content) instead of hand-building MIME — see below. |
| ConfigurationSetName | — | Not needed. Tracking and event delivery are per-send flags and webhooks. |
| Templates (SendTemplatedEmailCommand) | templateId | eusend has server-side templates; see the docs for the variable syntax |
If you send over SMTP (or nodemailer)
Many SES setups actually send through nodemailer pointed at the SES SMTP endpoint. That path migrates without touching application code — swap the transport and delete the IAM SMTP credential dance:
// Before: email-smtp.eu-west-1.amazonaws.com:587, IAM-derived SMTP credentials
// After — fixed username, API key as password, implicit TLS on 465 (not STARTTLS)
const transport = nodemailer.createTransport({
host: 'smtp.eusend.dev',
port: 465,
secure: true,
auth: { user: 'eusend', pass: process.env.EUSEND_API_KEY },
})The plumbing you get to delete
This is usually the real win. A production SES setup carries a stack of supporting pieces that eusend replaces with built-ins:
| On SES you run | On eusend |
|---|---|
| SNS topics + subscriptions for bounces and complaints | Signed webhooks: email.bounced, email.complained, email.delivered, plus opens and clicks — HMAC-SHA256 signed, no SNS confirmation handshake |
| Your own suppression handling | Hard bounces and complaints are suppressed automatically |
| Configuration sets + event destinations for open/click tracking | trackOpens / trackClicks flags, on by default, with a built-in analytics dashboard |
| CloudWatch alarms on bounce rate to protect your account | Platform-level monitoring — you see your rates in the dashboard and we flag problems before they hurt you |
What's honestly different
- Attachments without the raw MIME. If you reached for
SendRawEmailCommandjust to attach files — PDF invoices are the classic case — you no longer hand-build MIME: pass anattachmentsarray with base64contentand afilename(optionalcontent_type/content_id). Up to 20 files, 10 MB combined per message. - Price per email is higher than raw SES. SES is the cheapest raw pipe there is. What you're paying for instead is everything in the table above, plus deliverability being someone's actual job. Compare against SES plus the engineering time the plumbing costs you, not SES alone — pricing here.
- Volume ramps instead of a sandbox ticket. Where SES makes you request production access, eusend starts new accounts with a conservative daily ceiling that lifts automatically as you send cleanly. High steady volume from day one? Talk to us first.
- Bring your suppression list.Export it from the SES account-level suppression list so historical bounces don't repeat on the new platform.
Before you flip production
- Verify your sending domain and add its DKIM, SPF, and DMARC records — the Domains page generates them. You'll be swapping out the SES DKIM CNAME records for eusend's.
- Migrate against an
eu_test_API key first — test sends are accepted and tracked but never delivered — then switch toeu_live_. - Leave the SES identity and SNS plumbing in place for a week or two after cutover, then tear it down once nothing flows through it.