Short answer, speed versus developer experience versus control #
Transactional email, magic links, verification codes, receipts, password resets, must arrive quickly and exactly once in spirit. Marketing mail tolerates delay and batching. Transactional does not. A login code arriving in twenty minutes is not late mail. It is a broken product.
Think of it as registered mail. Regular post goes in the pile. Registered mail gets tracked, signed, and confirmed at every handoff. Auth emails and receipts are registered mail. Choose the postal counter accordingly.
Use built-in email to ship auth and notifications now with minimal configuration. Choose a developer-focused provider like Resend for a clean sending API, readable logs, and webhook events. Choose SES when your team already lives in AWS and prefers infrastructure-level control. Every path still demands the same fundamentals: verified sender identity, bounce and complaint handling, and a suppression list.
Try it: UTM Builder — which tags sender links so delivery lifts stay measurable.
What actually changes between options? #
Built-in email abstracts the provider away. You get speed and fewer keys to manage, with less visibility into delivery, reputation, and per-message diagnostics. Perfect for prototypes and MVPs where the login path must simply work this week.
A transactional API provider optimizes for developers. Resend's Node.js docs show the shape: install the SDK, send with a verified sender, handle the returned data or error object, add idempotency keys for safe retries. Templates, per-environment keys, delivery logs, and webhooks for delivered, bounced, and complained events come along. You trade some infrastructure control for iteration speed.
SES optimizes for operators. Amazon's sending docs cover console, SMTP, and raw API paths for test sends and bulk pipelines alike. You gain regions, configuration sets, and fine-grained IAM control, and you own more setup and observability wiring in return.
Price structures differ honestly. Resend's pricing opens with a free tier of 3,000 emails monthly and scales through paid tiers with per-thousand overage rates. SES pricing runs pay-as-you-go on volume sent and received, with no contracts. Neither price rescues a missing sender identity. That work is DNS and policy regardless of logo.
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: 'Your App <[email protected]>',
to: ['[email protected]'],
subject: 'Your sign-in link',
html: '<p>Click to sign in. This link expires in 15 minutes.</p>',
idempotencyKey: `magic-link/${userId}/${attemptId}`
});
if (error) {
console.error(error);
return;
}Note the idempotency key: retries of the same logical send carry the same key, so network hiccups cannot double-mail the user. Small habit, large professionalism.
How do the options compare side by side? #
| Criterion | Built-in | Resend-style API | SES |
|---|---|---|---|
| Time to first send | Fastest | Fast | Slower, more setup |
| Logs and debugging | Minimal | Strong, message-level | Powerful but you wire it |
| Bounce webhooks | Abstracted | Built-in event model | Available via AWS plumbing |
| Sender identity work | Still required | Still required | Still required, more knobs |
| Multi-environment keys | Platform-managed | Simple rotation | IAM roles and policies |
| Best fit | Prototype, auth MVP | Product team shipping fast | AWS-centered team |
Frame the choice as operational posture, not quality tier. Each delivers reliably when identity and list hygiene are correct. Each fails identically when they are not.
Which criteria decide reliably? #
Separate transactional from marketing streams. Never mix receipts and newsletters on the same identity if you can avoid it. Transactional reputation should not suffer because a campaign drew complaints. Use separate senders or subdomains and keep content types distinct. This single decision prevents the most common deliverability tragedy: password resets landing in spam because marketing pushed too hard.
Verify sender identity early. Publish SPF, DKIM, and DMARC, and align the From domain. Amazon's DKIM docs detail the signing options, including managed keys with 2048-bit defaults, but the principle is provider-neutral: cryptographic proof that your domain authorized the mail. Switching providers without fixing identity just relocates the problem.
Handle bounces with semantics in addition to logs. Hard bounces are permanent: stop sending and mark the address. Soft bounces are temporary: retry with backoff. Complaints mean stop marketing sends and investigate. Webhooks should update user contact state instead of only appending to a log nobody reads.
Maintain a suppression list and check it before every send. Addresses that bounced, complained, or unsubscribed stay excluded across all paths. Repeat sends to known-bad addresses burn reputation and budget simultaneously.
Treat auth emails as critical infrastructure. Magic links and one-time codes need short delivery time, single-use tokens, expiration windows, and rate limits. Log send attempts without logging secrets. Monitor this path like payments, because when login mail fails, nobody can use the product at all.
How do you warm up and monitor a new sender? #
New domains and IPs start with zero reputation, so mailbox providers watch early traffic closely. Ramp volume gradually to engaged recipients first: recent signups, active users, confirmed opt-ins. These addresses open, click, and rarely complain, which teaches receivers your mail is wanted. Double cautiously on clean metrics. Pause the ramp on any bounce or complaint spike until you find the cause.
Separate the streams from day one. Transactional mail on its own subdomain and identity, marketing on another. That way a marketing experiment can never throttle sign-in emails, and each stream builds its own reputation ledger.
Watch the dashboards that matter: delivery rate, hard bounce rate, complaint rate, and time-to-inbox for auth codes specifically. Set alerts on the auth path. A broken welcome email is silent churn: users who never got in rarely file tickets, they just leave. Review suppression growth weekly. Sudden jumps point at list quality or acquisition problems upstream, and catching them early is the difference between a bad afternoon and a burned domain.
Verdict, start simple and graduate to control #
Launching auth in an app: start with built-in email to unblock sign-in, receipts, and notifications. Verify your sender domain even on the simple path, because identity work transfers when you graduate.
Move to a dedicated provider when you need per-message logs, webhook-driven state updates, separate dev and production keys, or custom domain reputation management. Pick the developer-API style for shipping speed, SES when AWS integration and IAM control outweigh setup cost.
Whichever counter you choose, the non-negotiables never change: verified identity, bounce handling with suppression, transactional and marketing separation. Deliverability is mostly hygiene, not provider magic. Registered mail arrives because someone tracks every handoff. Be that someone.
See how BYOB wires auth emails
What are the trade-offs? #
The post recommends built in sending to start, then graduating to a developer API or SES when logs, webhooks, separate keys, or per product reputation demand it. That follows the Resend Node.js docs plus pricing and the SES sending plus DKIM plus pricing docs cited above.
| Where built in wins | Where it loses |
|---|---|
| Fastest first send with least setup | Least visibility into per message logs and delivery timing |
| Platform managed keys across environments | Reputation and suppression controls stay abstracted |
| Enough for auth MVP and prototypes | Custom domains and webhook driven state need a dedicated sender |
Pick Resend style APIs for shipping speed with message level logs, and SES when AWS integration plus IAM control outweigh setup cost at volume.
Who this is for (and who should skip it) #
This post helps builders choosing how to send auth codes and receipts so they arrive. If you weigh developer ease against AWS control and deliverability risk, the criteria here decide the path.
Skip self running email before you need hard control over suppression and reputation. Start with the built in path or a managed API, then move to SES when volume or ownership demands it.
- Best for developers shipping auth codes and receipts that must arrive in seconds.
- Best for startups starting simple with built-in mail then graduating to Resend or SES.
- Best for small teams sorting sender identity, bounces, and suppression before scaling volume.
What we learned building this #
BYOB ships with an email broker for magic links and auth flows so projects get sending without new provider setup, and the auth docs note that teams can bring their own provider later for sender reputation. That split matches the post framing of built in simplicity versus managed API ease versus full control. Delivery, bounces, and suppression stay behind the broker until a team graduates to a dedicated sender for production brand and policy reasons.