Client Area

Email Services Compared — SendGrid, AWS SES, Mailgun, Postmark, Resend

ByDomain India Team·DomainIndia Engineering
6 min read24 Apr 20263 views
# Email Services Compared — SendGrid, AWS SES, Mailgun, Postmark, Resend
TL;DR
Sending email from your DomainIndia-hosted app via SMTP is fine for occasional use. Anything transactional (receipts, OTPs, password resets) needs a dedicated email API — better deliverability, dashboards, suppression lists. This guide compares the five major options by price, deliverability, API quality, and India-market features.
## Why not just use SMTP from your app? Options: 1. **PHP `mail()`** / Node's `nodemailer` → SMTP via `localhost` — poor deliverability, emails land in spam 2. **Direct SMTP to Gmail** — daily limits, no dashboards, Gmail bans apps that spam 3. **DomainIndia email hosting** — good for small volumes (newsletters), but transactional needs dedicated infra 4. **Email API (SendGrid, SES, etc.)** — purpose-built for transactional, best deliverability For transactional email (>100/day), use an API. Your IP is shared with thousands of good senders; dedicated IPs available for high volumes. ## The five major options
ServiceFree tierPaid fromBest forIndia notes
SendGrid (Twilio)100 emails/day$19.95/mo (50K)General-purposeGood Indian card support
AWS SES200 emails/day (in EC2)$0.10 per 1KCost-sensitive, AWS ecosystemLower per-email cost
Mailgun100 emails/day (3 mo)$15/mo (10K)Developers, complex routingMid-tier
Postmark100 emails/month$15/mo (10K)Transactional purist (no marketing)Premium deliverability
Resend3K/mo, 100/day$20/mo (50K)Modern DX, React email templatesNewest, great API
## Decision tree **"Just want it to work, don't care much":** - Small volume: Resend (best DX, 3K/mo free) - Medium: SendGrid or Mailgun - High volume: AWS SES (cheapest) **"Best inbox placement, won't compromise":** - Postmark — industry-leading deliverability, transactional-only policy **"Already use AWS / cost-sensitive":** - AWS SES — $0.10/1K is unbeatable **"Want to include React/HTML templates":** - Resend — ships with `react-email` integration **"Need SMS + Email + WhatsApp unified":** - SendGrid (Twilio owned) or Mailgun + Twilio ## Deliverability — the real differentiator Same SPF/DKIM/DMARC setup, same mail content — different services have different delivery rates. Approximate inbox placement (2026, based on public reports):
ServiceGmail inbox %Outlook inbox %India local ISPs %
Postmark99%95%93%
Resend97%93%91%
SendGrid96%92%90%
Mailgun95%91%88%
AWS SES93%88%85% (improves with dedicated IP)
Margins matter at scale — 2% difference on 1M emails = 20,000 missed customers. ## Setup — all five are similar Pattern: 1. Sign up + verify domain ownership 2. Add SPF + DKIM DNS records they provide 3. Get API key 4. Send via HTTPS POST 5. Configure webhooks for delivery events + bounces ### Example — Resend (simplest) ```bash npm install resend ``` ```typescript import { Resend } from 'resend'; const resend = new Resend(process.env.RESEND_API_KEY); await resend.emails.send({ from: '[email protected]', to: '[email protected]', subject: 'Welcome!', html: '

Thanks for signing up

', }); ``` ### Example — SendGrid ```bash npm install @sendgrid/mail ``` ```typescript import sgMail from '@sendgrid/mail'; sgMail.setApiKey(process.env.SENDGRID_API_KEY); await sgMail.send({ from: '[email protected]', to: '[email protected]', subject: 'Welcome!', html: '

Thanks for signing up

', }); ``` ### Example — AWS SES ```bash npm install @aws-sdk/client-sesv2 ``` ```typescript import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2'; const ses = new SESv2Client({ region: 'ap-south-1' }); await ses.send(new SendEmailCommand({ FromEmailAddress: '[email protected]', Destination: { ToAddresses: ['[email protected]'] }, Content: { Simple: { Subject: { Data: 'Welcome!' }, Body: { Html: { Data: '

Thanks!

' } }, }, }, })); ``` ## Template management Three approaches: **1. In-code templates** (Resend + react-email): ```tsx import { Html, Head, Body, Heading } from '@react-email/components'; export function WelcomeEmail({ name }) { return ( Welcome {name}! ); } await resend.emails.send({ from: '[email protected]', to: '[email protected]', subject: 'Welcome!', react: , }); ``` Component-driven, previewable, testable. **2. Provider-hosted templates** (SendGrid, Mailgun): Create template in dashboard; reference by ID: ```typescript await sgMail.send({ templateId: 'd-abc123...', dynamicTemplateData: { name: 'Rajesh', orderId: 'ORD-1234' }, }); ``` Marketing team can edit without deploys. **3. MJML + Nunjucks** (self-hosted): MJML compiles to responsive HTML. Template in git, render at send time. See `mjml.io`. ## Webhooks — track what happens Every service sends webhooks for: - `delivered` — receiver accepted - `opened` — user opened (requires tracking pixel) - `clicked` — user clicked link - `bounced` — undeliverable (hard vs soft) - `complained` — user marked as spam - `unsubscribed` — user opted out Handler: ```typescript app.post('/webhook/email', express.raw({ type: 'application/json' }), (req, res) => { // Verify signature (per provider) const events = JSON.parse(req.body); for (const e of events) { if (e.event === 'bounce') { // Add to suppression list db.suppressionList.create({ email: e.email, reason: 'bounce' }); } if (e.event === 'spamreport') { db.user.update({ where: { email: e.email }, data: { suppressed: true } }); } } res.sendStatus(200); } ); ``` **Critical:** never send to suppressed emails. Bounce rate >5% damages your domain reputation. ## India-specific notes - **Mobile numbers for email verification** — some Indian apps require phone + email; plan for both - **Hindi/regional language emails** — all providers support UTF-8; some providers' templates have RTL/Hindi rendering issues — test - **GST on bills** — most providers bill from US; your accountant may need GST self-reverse-charge handling - **Card payments** — Razorpay doesn't work for subscription to US services; Indian international cards work but watch for 3D Secure friction ## Dedicated IP — when to buy Dedicated IP: ₹8,000-₹20,000/mo add-on. Consider when: - Volume >500K/mo - You need predictable deliverability (shared IPs have mixed reputation) - Scheduled bulk sends (newsletters) Warm up dedicated IP slowly — jumping from 0 to 100K/day triggers spam filters. ## Cost comparison (at 100K/month)
ServiceMonthly cost (100K emails)Extras
SendGrid Essentials$19.95Validation API
AWS SES$10 (100K × $0.10/1K)In ap-south-1 region
Mailgun Foundation$35Log retention
Postmark$15 (10K batch pack) — or $50 for 100KTransactional-only
Resend Pro$20Modern DX
For 100K/month, AWS SES wins on cost. Postmark wins on deliverability. ## Common pitfalls ## FAQ
Q Can I use DomainIndia email hosting for transactional?

For ≤100 emails/day — fine. Above that, deliverability drops on shared infrastructure. Use a dedicated transactional API.

Q Best service for OTPs?

Speed matters — Postmark delivers in 1-2 seconds. SendGrid and Resend similar. Avoid SES for OTPs (slightly higher latency on cold calls).

Q Multiple services for redundancy?

Advanced pattern: primary + fallback. Use Resend; fall back to SendGrid on API outage. Libraries like node-mailer-multi support this.

Q SMS instead of email?

India SMS ₹0.20-0.50 per message (DLT-registered), email ₹0.02-0.05. SMS faster, email cheaper. Use SMS for critical OTPs; email for everything else.

Q Do I need separate sender for marketing vs transactional?

Yes — use noreply@ or alerts@ for transactional, news@ or subdomain for marketing. Isolates reputation if marketing gets flagged.

Send transactional email reliably from your DomainIndia-hosted app. View hosting plans

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket