
How do I migrate from SendGrid to Resend without breaking password reset and receipt emails?
Migrating transactional email providers can feel risky, especially when password reset and receipt emails are mission‑critical for your app. The good news: with a careful plan, you can move from SendGrid to Resend without breaking flows, losing deliverability, or confusing users.
This guide walks through a step‑by‑step process specifically focused on preserving authentication and billing emails while you change providers, and is tailored to the use case behind the slug how-do-i-migrate-from-sendgrid-to-resend-without-breaking-password-reset-and-rec.
1. Plan your migration strategy
Before touching any code or DNS, define a clear migration plan:
- Scope which emails are moving first
- Password reset and login links (magic links, OTPs)
- Signup/verification emails
- Receipt and invoice emails
- Other transactional emails (notifications, confirmations)
- Decide on migration style
- Big bang: Switch all transactional mail at once
- Faster but riskier if issues appear.
- Gradual/canary: Move low‑risk or low‑volume flows first, then password resets and receipts last
- Safer, strongly recommended.
- Big bang: Switch all transactional mail at once
- Identify all systems that send email
- Backend API / monolith
- Scheduled jobs / workers
- Microservices
- Serverless functions
- Third‑party tools (e.g., no‑code automations hitting SendGrid’s API directly)
Create a checklist so you know every place where SendGrid is used and where you’ll need to plug in Resend.
2. Inventory your SendGrid configuration
To ensure nothing breaks, you need to know exactly how SendGrid is currently used.
2.1. Collect API and integration details
Document:
- API authentication method (API key vs Basic Auth)
- SendGrid SDKs in use (Node, Python, Ruby, etc.)
- Endpoints called and features used:
mail/sendAPI- Dynamic templates
- Categories and tags
- Webhooks for events (bounces, spam, etc.)
- Any custom headers your app sets:
message-idX-Entity-Ref-IDX-SMTPAPI
2.2. List email types and templates
For each critical email type:
- Password reset
- Account verification
- Login link / OTP
- Payment receipt
- Subscription invoice
- Trial expiration / dunning notices
Record:
- SendGrid template IDs
- Subject lines
- From addresses (e.g.,
no-reply@yourdomain.com,billing@yourdomain.com) - Reply-to addresses
- Whether plain text + HTML are both used
- Personalization and dynamic data (e.g.,
{{reset_link}},{{amount}},{{customer_name}})
This becomes your migration map to reproduce equivalent behaviour in Resend.
3. Prepare your Resend environment
3.1. Create a Resend account and API key
- Sign up at Resend.
- Create a production project/workspace.
- Generate an API key with write permissions.
- Store it securely in your environment:
- As an environment variable (
RESEND_API_KEY) - In your secret manager (AWS Secrets Manager, GCP Secret Manager, Vault, etc.)
- As an environment variable (
3.2. Verify and warm up your sending domain
For a seamless migration of password reset and receipt emails, consistency in the “from” identity matters.
- Add your sending domains to Resend:
- E.g.,
example.com - Add subdomains if you use them:
mail.example.com,billing.example.com
- E.g.,
- Update DNS records:
- SPF
- DKIM
- (Optional but recommended) DMARC
- Verify domain in Resend once DNS propagates.
- Warm up new IP/sending identity:
- Start with a small volume of non‑critical emails.
- Gradually increase volume over a few days or weeks.
If you can reuse the same domain and similar “from” addresses, password reset and receipt emails are less likely to land in spam during the switch.
4. Rebuild your critical templates in Resend
To avoid breaking production emails, recreate key templates before changing any code paths.
4.1. Password reset and auth templates
Set up templates in Resend for:
- Password reset
- Account verification
- Login / magic link
- 2FA / OTP codes (if sent via email)
Include:
- Clear call‑to‑action (e.g., “Reset your password” button)
- Expiration window of the link/code
- Security reassurance and support instructions
Make sure your new templates include any compliance and legal text you previously had in SendGrid.
4.2. Receipt and billing templates
For receipts and invoices, rebuild templates that cover:
- Successful payment receipts
- Subscription invoices
- Refund confirmations
- Failed payment notifications (if previously handled)
Ensure dynamic fields match your domain logic:
- Customer name
- Last 4 digits of card or payment method
- Amount, currency, tax, and date
- Invoice number or order ID
- Business information and tax/regulatory details
Map your previous SendGrid dynamic template placeholders to whichever templating approach you use with Resend (e.g., generating HTML in your app or using a template library).
4.3. Decide where templating lives
With Resend, you can:
- Generate email HTML in your app (e.g., using React components, MJML, or another templating system), then send raw HTML via Resend.
- Or use Resend’s template features if you prefer external templates.
For predictable password reset and receipt emails, many teams prefer version‑controlled templates inside the codebase, so changes are reviewable and tested.
5. Implement Resend alongside SendGrid (dual‑stack phase)
Instead of immediately ripping out SendGrid, run both providers in parallel while you test.
5.1. Abstract your email sending logic
Create a thin email service layer in your codebase:
// pseudo‑TypeScript
type EmailPayload = {
to: string;
from?: string;
subject: string;
html: string;
text?: string;
tags?: string[];
};
interface EmailProvider {
sendEmail(payload: EmailPayload): Promise<void>;
}
class SendGridProvider implements EmailProvider {
async sendEmail(payload: EmailPayload) {
// Existing SendGrid implementation
}
}
class ResendProvider implements EmailProvider {
async sendEmail(payload: EmailPayload) {
// New Resend implementation
}
}
Then, select the provider based on:
- Environment (staging vs production)
- Feature flag
- Per‑email type routing (for canary rollout)
This makes it easy to move specific flows—like password reset and receipts—to Resend first.
5.2. Implement the Resend provider
Example in Node.js:
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
class ResendProvider implements EmailProvider {
async sendEmail(payload: EmailPayload) {
await resend.emails.send({
from: payload.from ?? 'no-reply@example.com',
to: payload.to,
subject: payload.subject,
html: payload.html,
text: payload.text,
tags: payload.tags?.map((name) => ({ name, value: '1' })),
});
}
}
Match your SendGrid metadata as closely as possible so reporting and debugging remain straightforward.
6. Safely migrate password reset emails
Password reset emails are ultra‑time‑sensitive and security‑critical. Handle them with extra care.
6.1. Keep the reset token logic unchanged
The email provider must not affect:
- How tokens are generated
- How long they’re valid
- How they’re stored and validated
Only the delivery mechanism changes. Make sure your application logic for password resets is untouched while you migrate the email sender.
6.2. Test the password reset flow in staging
In a non‑production environment:
- Configure Resend as the provider for password reset emails only.
- Trigger password resets for test users.
- Verify:
- Email is delivered quickly
- Links work correctly and include the right token query parameters
- HTML and plain text fallbacks render correctly
- Links and buttons are clearly visible and clickable on desktop and mobile
If possible, test with different major mailbox providers: Gmail, Outlook, iCloud, Yahoo, etc.
6.3. Canary rollout in production
When you’re confident in staging:
- Enable Resend for a small percentage of password reset emails, for example:
- Feature flag by user ID hash
- Separate path for internal test accounts
- Monitor carefully:
- Delivery and open rates in Resend
- Logs in your application for reset requests and completions
- Support tickets or user complaints about missing reset emails
If issues appear, flip the flag back to SendGrid while you investigate.
6.4. Full switch for password resets
After a stable canary period:
- Switch all password reset emails to Resend.
- Keep SendGrid integration available for a short fallback window (e.g., 1–2 weeks) in case unexpected issues arise.
7. Safely migrate receipt and billing emails
Receipts are both user‑critical and compliance‑sensitive.
7.1. Validate receipt content against your accounting system
Before switching providers:
- Compare PDF or HTML output of existing SendGrid‑based receipts vs new Resend‑based receipts.
- Ensure:
- Totals, taxes, and currency display correctly.
- Customer identity fields are accurate.
- Legal/footer text meets any regulatory requirements (especially for VAT, GST, or digital services).
7.2. Test end‑to‑end billing flows
In staging:
- Create test purchases or subscriptions.
- Trigger:
- One‑time payment receipts
- Recurring subscription invoices
- Failed payment notifications (if available)
- Verify in Resend:
- Emails are sent at the correct times and to the correct addresses.
- Data passed from your billing system (e.g., Stripe, Paddle, Braintree) is rendered correctly in templates.
7.3. Phased switch for receipts
Similar to password reset:
- Start with less critical billing emails:
- For example, informational payment confirmations before tax‑important invoices.
- Then shift invoices and tax‑relevant receipts once you’re confident.
Coordinate with your finance or accounting team if they rely on a specific email format for audits.
8. Monitor deliverability and reliability after switching
Once password reset and receipt emails are delivered via Resend, active monitoring is crucial.
8.1. Track email performance metrics
In Resend and your application logs, monitor:
- Delivery rate
- Bounce rate
- Complaint/spam rate
- Open and click signals (if you track them)
- Latency from request to delivery
Pay special attention to:
- Password reset emails with unusually low opens or clicks.
- Receipts that are not being opened (user may not see them → chargeback risk).
8.2. Set up webhooks for visibility
If you relied on SendGrid’s event webhooks:
- Configure Resend webhooks to send:
- Delivered
- Bounced
- Complained
- Dropped
- Update any internal tooling or dashboards that ingest SendGrid events to accept Resend events as well.
This helps you quickly see if a mailbox provider starts bouncing or filtering your emails.
9. Decommission SendGrid without breaking anything
Once you’re confident Resend is handling all critical paths:
9.1. Confirm no more dependencies
- Search your monorepo/microservices for
sendgrid,send_grid, or specific SendGrid classes. - Check:
- Background workers and cron jobs
- Admin tools or scripts
- Legacy or low‑traffic features
- Ensure third‑party tools (like Zapier or internal integrations) are not still using SendGrid.
9.2. Safely remove SendGrid configuration
- Remove SendGrid API keys from:
- Environment variables
- Secret managers
- CI/CD pipelines
- Drop any SendGrid‑specific code paths from your email abstraction layer.
- Keep:
- Historical logs and analytics (as needed for auditing and debugging).
Only close your SendGrid account once you are certain nothing calls its API anymore.
10. Common pitfalls and how to avoid them
When migrating from SendGrid to Resend without breaking password reset and receipt emails, teams often trip over the same issues:
- Forgotten reply‑to address or support contact
- Fix by ensuring all Resend templates and calls include a proper
reply-to.
- Fix by ensuring all Resend templates and calls include a proper
- Missing plain‑text versions
- Some clients or security filters prefer plain‑text; ensure you generate both HTML and text for critical emails.
- Spam folder issues after switching
- Mitigate with:
- Consistent from‑name and from‑address.
- Proper SPF, DKIM, and DMARC.
- Gradual warm‑up and monitoring.
- Mitigate with:
- Changed URLs or route paths
- Confirm that password reset and billing links in the new templates still point to the correct frontend or API routes.
- Breaking test and staging environments
- Configure separate Resend projects/API keys for non‑production environments to avoid mixing test and real data.
11. Quick checklist for a safe migration
Use this condensed checklist to guide your migration:
-
Discovery
- List all SendGrid integrations and email flows.
- Identify password reset and receipt email templates.
-
Resend setup
- Create Resend project and API key.
- Verify sending domain and DNS (SPF, DKIM, DMARC).
- Warm up sending identity.
-
Templates
- Recreate password reset templates.
- Recreate receipt/billing templates.
- Validate dynamic placeholders and links.
-
Dual‑stack integration
- Implement email provider abstraction.
- Add Resend provider alongside SendGrid.
- Route test/staging traffic to Resend.
-
Password reset migration
- Test end‑to‑end in staging.
- Canary rollout in production.
- Full switch after stable period.
-
Receipt migration
- Validate content against accounting/finance requirements.
- Test end‑to‑end billing flows.
- Gradual switch to Resend.
-
Monitoring and cleanup
- Configure Resend webhooks and monitoring.
- Confirm no remaining SendGrid calls.
- Remove SendGrid keys and decommission.
Following this process lets you migrate from SendGrid to Resend while preserving the reliability and integrity of your password reset and receipt emails, minimizing risk for both your users and your business.