# Amazon SES vs Customer.io

Source: https://wraps.dev/versus/amazon-ses-vs-customer-io

Customer.io is a behavioural workflow engine that happens to send email. SES is the sending with no behaviour attached. Teams comparing them are deciding whether lifecycle logic belongs in a product or in their own codebase.

Every SaaS team eventually asks whether the onboarding sequence should live in a platform or in the application, and this pair is that question in its purest form. Customer.io ingests events and attributes, holds a profile per user, and lets a non-engineer compose the logic that decides who receives what and when. SES takes a rendered message and an address. The gap between them is not sending — it is a workflow engine, a data model and an editor, and the argument is entirely about whether those belong to you.

## At a glance

|   | Amazon SES | Customer.io |
| --- | --- | --- |
| What it is | Raw sending infrastructure from AWS | Behavioral messaging and lifecycle automation |
| Published pricing | $0.10 per 1,000 emails on à la carte. New accounts are defaulted to the Essentials plan at $0.16 per 1,000; Pro is $105/mo + $0.22 per 1,000 and Enterprise $500/mo + $0.23 per 1,000. Plans are per-account, per-Region. | Essentials $100/mo for 5,000 profiles, then $0.009 per additional profile — roughly $145 at 10K, $505 at 50K, and $955 at 100K. Premium starts at $1,000/mo. |
| Best for | Teams already on AWS with an engineer willing to own the plumbing. | Behavioral lifecycle messaging a marketing team owns day to day. |
| Watch out for | Production access is an application AWS can refuse, and new accounts start sandboxed to verified addresses. No dashboard, no templates, and nothing stores your events until you build it. | You pay per profile whether or not you ever message them, so signups you never email still raise the bill. |

Prices are each vendor's published list prices, verified August 2026. Check the vendor's own page before you sign anything.

## Where they actually differ

### The data model, which is the real difference

Amazon SES

SES has no model of a user. There is a destination address and a message, and that is the whole vocabulary. If the decision to send depends on what someone did last Tuesday, that decision happens in your application against your database, and SES is told the answer. For teams whose product data is already rich and already queryable, this is not a gap at all — it is a refusal to duplicate something they have.

Customer.io

A profile per person, fed by an event stream and an attribute payload from your application, with segments evaluated continuously against it. The platform holds a second copy of the part of your user model that matters for messaging. That duplication is the price of admission and also the entire benefit, because it is what lets somebody who cannot query your database express when a user has not completed setup in five days.

### What building the workflow engine actually involves

Amazon SES

More than the first estimate and less than the horror stories. A credible in-house sequence needs a trigger source, a scheduler that survives a deploy, per-user state so a restart does not re-send, exit conditions when the user does the thing you were nagging about, a suppression check at send time, a way to change copy without shipping code, and enough observability to notice the sequence stopped firing. Each piece is a day. The integration and the edge cases are the quarter.

Customer.io

All of that exists and is the product. Workflows are built in a visual editor with branches, waits, exit conditions and A/B splits, and they run whether or not your deploy went well. The parts that are hard to build yourself — idempotency across restarts, timezone-aware sends, a person leaving a branch mid-flight — are handled and mostly invisible. That invisibility is why the build estimate is always low.

### The bill, and what it is charged against

Amazon SES

Messages. Somebody who signed up, never activated and will never be emailed again costs nothing at all. For a product with a wide free tier and a long tail of abandoned accounts, that property is worth more than the per-message rate, because it means list growth and cost growth are decoupled entirely.

Customer.io

Profiles, whether or not you ever message them, with the entry tier covering a fixed count and each additional profile adding a small increment. The structural consequence is that a freemium product with a large dormant signup base pays for people it has given up on. Profile hygiene becomes a recurring billing activity, and it is the first lever to pull before concluding the platform is too expensive.

### Who changes the copy on a Thursday

Amazon SES

An engineer, with a pull request and a deploy. That is entirely appropriate for transactional messages where the content is generated from data and correctness matters more than tempo. It is a poor fit for lifecycle messaging, where the value comes from iterating on copy and timing quickly, and where a two-day round trip through the release process means the iteration simply does not happen.

Customer.io

Whoever owns lifecycle, usually in marketing or growth, without engineering involvement once the event integration exists. The independence is the point. The cost is the familiar one for any system where business logic lives outside the repository: the behaviour is not in version control, is not covered by your tests, and the reason a particular email fires is discoverable only by opening the platform.

### Transactional mail, and where it ends up

Amazon SES

This is SES's home ground and it is very hard to beat here. Receipts, password resets and notifications are high volume, code-generated, latency-sensitive and completely uninterested in segmentation. Running them through SES costs almost nothing and keeps them on a path whose reputation you control, independent of whatever marketing is doing that week.

Customer.io

Customer.io can send transactional messages and many teams route everything through it for the single-pane benefit. The consequence worth thinking about is billing and coupling: transactional recipients become profiles, and profiles are the billed unit, so your cheapest and highest-volume traffic starts influencing the price of your lifecycle tooling. A split architecture avoids that and costs you one reconciliation.

### Channels beyond email

Amazon SES

SES is email only. SMS lives in a separate AWS service with its own registration, its own approvals and its own console, and push is a third. Building a cross-channel sequence on AWS is possible and is several projects, each with its own compliance steps, coordinated by code you write. Nothing about the pieces is designed to be used together.

Customer.io

Email, push, SMS, in-app and webhooks are all channels inside one workflow, with per-person preferences honoured across them. For a product that genuinely needs to reach people in more than one place, orchestrating that from one engine is a substantial simplification and is hard to reproduce piecemeal. If you only ever send email, you are paying for an engine whose shape you are not using.

### Deliverability and whose reputation is in play

Amazon SES

Yours, isolated, visible in your own metrics, and entirely your responsibility to defend. A new identity starts cold and needs warming. Once warm it stays yours across any change to the tooling above it, which is the durable half of this argument — the reputation is an asset on your side of the line rather than a benefit of a subscription.

Customer.io

Shared infrastructure with a deliverability function attached and a commercial interest in keeping the pool healthy. There are also arrangements where a customer sends through their own provider credentials, which changes this dimension considerably, so check what your plan actually supports rather than assuming either answer. Whichever applies, the operational monitoring is somebody else's job by default.

### What the exit looks like

Amazon SES

Leaving SES is a code change, because the domains and the reputation attach to an account you keep. Nothing about your lifecycle logic is trapped anywhere, because it was always in your repository. This is the strongest structural argument for the build side and it is rarely weighed properly, because it is a benefit that only shows up on a day that has not happened yet.

Customer.io

Leaving means re-implementing every workflow somewhere else, because the logic lives in the platform rather than in your code. Profiles and events export; branching logic, wait steps and the accumulated judgement about timing do not, in any form that another system will accept. The migration cost grows with every sequence somebody adds, which is worth knowing while there are still only three of them.

## Pros and cons, side by side

### Amazon SES

Strengths

-   Somebody who signed up, never activated and will never be messaged again costs nothing, which decouples list growth from cost entirely for a product with a wide free tier.
-   The lifecycle logic stays in the repository, so it is reviewed, tested, greppable and covered by whatever you already do to keep the application correct.
-   Nothing about your user model gets duplicated into a vendor, which for a team whose product data is already rich is a refusal to maintain two sources of truth rather than a missing feature.
-   Leaving is a code change, because the verified domains and the earned reputation sit in an account that stays yours whatever else changes.

Trade-offs

-   There is no scheduler, no per-user workflow state and no exit condition, so the parts of a lifecycle build that overrun are all in front of you rather than behind you.
-   Every change to who receives what is a pull request and a deploy, which is correct for a receipt and fatal for a growth experiment somebody wanted to run this afternoon.
-   Push, SMS and in-app are separate AWS services with their own registrations, so a cross-channel sequence is several projects coordinated by code you write.
-   Nobody is watching your bounce rate, your complaint rate or your DMARC reports unless you build the thing that watches them and the alert that fires.

### Customer.io

Strengths

-   A profile per person, continuously evaluated against your segments, which is what lets somebody who cannot query your database express has not finished setup in five days.
-   Idempotency across restarts, timezone-aware sending and a person leaving a branch mid-flight are all handled, and their invisibility is exactly why in-house estimates come in low.
-   Email, push, SMS, in-app and webhooks are steps inside one workflow with per-person preferences honoured across all of them.
-   Whoever owns lifecycle changes the sequence without engineering involvement, which removes the release cycle from the path between an idea and a test.

Trade-offs

-   The meter counts profiles whether or not you ever message them, so a freemium product with a wide funnel pays monthly for the people it has already given up on.
-   The behaviour lives outside version control, so the reason a particular message fired is discoverable only by opening the tool and reading the branch somebody drew.
-   Workflows do not export in any form another platform will ingest, and the cost of that grows with every sequence added after the third one.
-   A misconfigured workflow can message the wrong segment at scale with no code review standing between the mistake and the send.

## Pick in thirty seconds

### Choose Amazon SES if

-   Your lifecycle logic is simple enough to live in the application, and the team would rather own it in version control than in a vendor's editor.
-   A large dormant signup base makes per-profile billing a charge for people you have already given up on.
-   The messages in question are transactional and code-generated, where segmentation adds nothing and unit cost adds up.
-   Reversibility matters: you want the reputation and the logic to stay on your side of the line so a future change is a refactor, not a migration.

### Choose Customer.io if

-   Growth or marketing should be able to change who receives what without a deploy, and the iteration speed is the point of the exercise.
-   The sequences involve branches, waits, exit conditions and timezone-aware sends, which is exactly the part of the build that runs long.
-   You need email, push and SMS coordinated by one engine with per-person preferences honoured across them.
-   Nobody on the team wants to own a scheduler whose failure mode is silently not sending anything for a week.

## What actually moves when you switch

In roughly the order you would do it. The expensive parts of an email migration are never the send call.

1.  Name the asymmetry before estimating anything. Moving onto SES means acquiring a scheduler, per-user state, an exit condition mechanism, a copy editor for non-engineers, bounce and complaint processing, a suppression story and a production access approval from AWS. Moving the other way hands all of that back and buys a per-profile bill. Only one of those directions has a quarter of engineering hidden inside it.
2.  Rewrite the Liquid rather than porting it. Customer.io renders Liquid against the profile at send time, so a template is full of conditionals, default filters and date formatting that execute on their infrastructure with access to attributes you never sent in the payload. SES either takes finished HTML or does flat token substitution. Every one of those expressions becomes application code, and the ones that silently fall back to a default are the ones you will not notice are missing.
3.  Transcribe every workflow by hand while there are still few of them. Triggers, wait durations, branch conditions, exit conditions and the accumulated judgement about timing exist as a diagram in the editor and as nothing anywhere else. There is no export that another system reads. A written description of each campaign, produced before anyone is under migration pressure, is the single highest-value hour on this list.
4.  Work out what a subscription topic becomes. Customer.io hosts a preference centre where a person opts out of a topic rather than out of everything, and the platform honours that on every subsequent send. SES has an account-level suppression list keyed to an address with only bounce and complaint as reasons, and configuration-set scoping on top. Topic-level preferences have no home in AWS, so they become rows you own and a check you perform immediately before every send.
5.  Repoint the identify and track calls, and count them first. The event stream that feeds the profiles is a set of call sites scattered through your application pointing at their API, and they do not stop when the subscription does — they keep succeeding against an account nobody is reading. Inventory them, decide where events land instead, and cut them over in the same change as the sending.
6.  Reproduce the timezone behaviour deliberately. Sending at nine in the morning local to each recipient is a per-profile attribute and a scheduler working together, and on SES it is a column, a job that wakes hourly and a decision about what to do with people whose timezone you never captured. That last group is usually larger than anybody expects and defaults badly if nobody chooses.
7.  Decide what happens to the non-email channels rather than discovering it. Push tokens and in-app message state live on the profile, and there is no AWS service that takes over that role without its own registration, its own console and its own consent handling. A sequence that currently reaches somebody by push when email fails simply stops doing so, and the fallback logic was a checkbox rather than code.
8.  Check whether reputation is already yours before assuming a cold start. Some arrangements send through the platform's pools and some send through credentials you supplied, and the two produce completely different warm-up plans. Confirm which one your account actually uses, then ramp across a subdomain either way, because the identity is new to the mailbox provider even when the domain is not.

## Questions to ask before you sign

Put these to a sales rep, or find the answer in the documentation before anyone quotes you a number.

1.  How many sequences do we run today, and could somebody write down what each one does without opening the editor?
2.  What share of our profiles have never received a message, and what would the invoice look like without them?
3.  Who changes lifecycle copy today, and how long does it currently take from idea to sent?
4.  Do any of our sequences depend on push, SMS or in-app, and what is the plan for those if the engine goes away?
5.  How many identify and track call sites exist in our codebase, and does anybody know where they all are?
6.  If the scheduler stopped firing on a Friday, what would tell us, and how long would it take?
7.  Are we comparing the subscription against the sending cost, or against the sending cost plus the engineering we would need to replace the engine?

## A third shape of answer

The trap on this pair is treating it as build everything or buy everything, when the expensive part of the build is narrow. What teams actually want is the workflow editor and the contact model without the per-profile bill and without the lifecycle logic becoming unportable. A platform layer over your own AWS account is one way to split that difference, and Wraps is one implementation — contacts are unlimited on every tier precisely because the dormant-signup problem is the thing that makes profile billing hurt. The honest costs are real: you need an AWS account and SES production access, an approval on AWS's timetable rather than ours, our SDKs cover TypeScript and Python only, our workflow engine is considerably less capable than Customer.io's and has no push or in-app channel, contacts and workflow state live in our database while only sending data and delivery events stay in your AWS, and we are not SOC 2 certified.

Wraps publishes this page. We are not one of the two vendors being compared here, and this note is on it because the tension above is one owning the AWS account actually addresses — not because it is on every page.

## Common questions

### How long does it really take to build drip campaigns on SES?

The first version takes about a week and the version you can trust takes a quarter. The week gets you a scheduled job that sends a sequence. The quarter gets you per-user state that survives deploys, exit conditions so people who converted stop receiving the nag, timezone handling, a suppression check at send time, an editor non-engineers can use, and alerting for the day the scheduler stops silently. The last item is the one teams discover by not having it.

### Why does Customer.io charge for users I never message?

Because the billed unit is the profile rather than the send, and a profile exists from the moment your application identifies someone. This is deliberate — the platform is storing and continuously evaluating those profiles against your segments whether or not a message results. The practical consequence for a freemium product is that dormant signups carry cost, and deleting or suppressing profiles you will never contact is a legitimate and frequently overlooked way to lower the bill.

### Can I use Customer.io for lifecycle and SES for transactional?

Yes, and it is a common and sensible split. Transactional mail is high volume and low complexity, so running it through the cheapest reliable path keeps it out of your profile count and off your lifecycle bill. Use separate subdomains so DKIM keys and reputation stay independent. The cost is two suppression concepts and the risk that someone who opted out in one system keeps hearing from the other, which needs deliberate reconciliation rather than good intentions.

### What happens to my workflows if I leave Customer.io?

Profiles and event history export cleanly. The workflows do not, in any form another platform will ingest — branches, wait steps, exit conditions and the accumulated tuning of timing and copy have to be rebuilt by a human reading the old ones. The cost scales with how many sequences exist, which is an argument for documenting them outside the tool early, while there are three of them rather than thirty.

### Is SES cheaper if I count the engineering?

At a large dormant user base, frequently yes, because per-profile billing and per-message billing diverge fastest exactly where freemium products live. At a small, engaged user base with complex sequences, usually not, because the engineering is a fixed cost that does not shrink with your size. Run the comparison with a real estimate of the build rather than a hopeful one, and include the maintenance rather than just the first delivery.

### What happens to Liquid templates if I move to SES?

They stop being templates and become code. Liquid is evaluated against the profile on the platform's side, which is how a message can branch on an attribute your send call never mentioned, apply a default when a field is empty and format a date in the recipient's locale. SES does flat token substitution or takes finished HTML. The conditionals move into your rendering layer, and the quiet hazard is the filters — a default that used to fill a gap now renders an empty string, and nothing fails loudly.

### How do I honour topic-level unsubscribes on SES?

You build it, because there is nothing to configure. SES suppression is keyed to an address with bounce and complaint as its only reasons, so a person who wants product updates but not the weekly digest has no representation in AWS at all. The working pattern is a preferences table, a hosted page behind a signed link, a List-Unsubscribe header that points at it, and a check immediately before every send. It is a small feature whose absence is a compliance problem rather than an inconvenience.

### Do my events keep flowing after I cancel?

Yes, and that is the trap. The identify and track calls are ordinary HTTP requests scattered through your application, and they keep returning success against an account you are no longer reading. Nothing breaks, nothing alerts, and six weeks later somebody notices the new system has a gap where the old call sites never got repointed. Inventory the call sites before the migration rather than during it, and cut them over in the same change that moves the sending.

### Can I keep the platform and move only transactional mail?

Yes, and it is usually the first move worth making. Receipts, resets and notifications are high volume, code-generated and uninterested in segmentation, so running them through SES lowers the sending cost and keeps transactional-only recipients out of the profile count. Use a separate subdomain so the two reputations stay independent, and be explicit about which system owns an opt-out — the failure mode of a split is somebody who unsubscribed in one place continuing to hear from the other.
