Back to Blog
๐Ÿšš
/5 min read/By SMTPfast Team

How to Migrate from SendGrid to SMTPfast

A step-by-step guide to moving your transactional email from SendGrid to SMTPfast. Includes code before and after for every language.

migrationsendgridtutorialgetting-started
Share:๐•in

Why Migrate?

If you are only using SendGrid for transactional emails, you are paying for features you do not use. SMTPfast gives you a simpler API and clearer pricing.

SendGrid is a powerful platform, but many developers only use a fraction of it. If your use case is sending password resets, order confirmations, and notifications, SMTPfast gets the job done with less complexity.

15 min
Typical migration time from SendGrid to SMTPfast

Step 1: Create Your SMTPfast Account

Sign up at smtpfa.st and verify your email address. No credit card required for the free tier (3,000 emails/month).

Step 2: Add Your Sending Domain

In the SMTPfast dashboard, go to Domains and add your sending domain. You will get:

  • 3 CNAME records for DKIM
  • An SPF include directive
  • A recommended DMARC record

Add these DNS records alongside your existing SendGrid records. Both can coexist during the migration.

# Your SPF record can include both during migration
v=spf1 include:sendgrid.net include:amazonses.com ~all

Step 3: Generate an API Key

Go to API Keys in the dashboard and create a new key with email:send scope. Copy it immediately - you will only see it once.

Store it as an environment variable:

export SMTPFAST_API_KEY=sf_live_your_new_key

Step 4: Update Your Code

Here is how the code changes for each language.

Node.js

Before (SendGrid):

const sgMail = require("@sendgrid/mail");
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

await sgMail.send({
  to: "[email protected]",
  from: "[email protected]",
  subject: "Your order has shipped",
  html: "<h1>Order shipped!</h1><p>Tracking: XYZ123</p>",
});

After (SMTPfast):

await fetch("https://smtpfa.st/api/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    from: "[email protected]",
    to: "[email protected]",
    subject: "Your order has shipped",
    html: "<h1>Order shipped!</h1><p>Tracking: XYZ123</p>",
  }),
});

You can remove the @sendgrid/mail dependency entirely. No SDK needed.

Python

Before (SendGrid):

from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

message = Mail(
    from_email="[email protected]",
    to_emails="[email protected]",
    subject="Your order has shipped",
    html_content="<h1>Order shipped!</h1><p>Tracking: XYZ123</p>",
)

sg = SendGridAPIClient(os.environ.get("SENDGRID_API_KEY"))
response = sg.send(message)

After (SMTPfast):

import requests
import os

response = requests.post(
    "https://smtpfa.st/api/v1/emails",
    headers={
        "Authorization": f"Bearer {os.environ['SMTPFAST_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "from": "[email protected]",
        "to": "[email protected]",
        "subject": "Your order has shipped",
        "html": "<h1>Order shipped!</h1><p>Tracking: XYZ123</p>",
    },
)

You can remove the sendgrid package. The requests library handles everything.

cURL

Before (SendGrid):

curl -X POST https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{"to": [{"email": "[email protected]"}]}],
    "from": {"email": "[email protected]"},
    "subject": "Your order has shipped",
    "content": [{"type": "text/html", "value": "<h1>Order shipped!</h1>"}]
  }'

After (SMTPfast):

curl -X POST https://smtpfa.st/api/v1/emails \
  -H "Authorization: Bearer $SMTPFAST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "[email protected]",
    "to": "[email protected]",
    "subject": "Your order has shipped",
    "html": "<h1>Order shipped!</h1>"
  }'

Notice how much simpler the payload is. No nested personalizations array, no content array with type fields. Just from, to, subject, and html.

Step 5: Map SendGrid Concepts to SMTPfast

SendGrid SMTPfast Notes
personalizations[].to to String or array of strings
personalizations[].cc cc Same format
personalizations[].bcc bcc Same format
from.email from String, supports "Name " format
reply_to.email reply_to String or array of strings
subject subject Same
content[].value (text/html) html Direct HTML string
content[].value (text/plain) text Direct text string
custom_args tags Array of {name, value} objects
headers headers Record of key-value pairs
Dynamic templates HTML with variables No template engine - use your own

Step 6: Update Webhooks

If you use SendGrid's Event Webhook, you will need to set up equivalent webhooks in SMTPfast.

SendGrid event types mapped to SMTPfast:

SendGrid Event SMTPfast Event
delivered delivered
bounce bounced
spam_report complained
open opened
click clicked

Update your webhook handler to accept SMTPfast's payload format:

// Before: SendGrid webhook
app.post("/webhooks/sendgrid", (req, res) => {
  // SendGrid sends an array of events
  const events = req.body;
  events.forEach((event) => {
    switch (event.event) {
      case "delivered": // ...
      case "bounce": // ...
    }
  });
  res.sendStatus(200);
});

// After: SMTPfast webhook
app.post("/webhooks/email", (req, res) => {
  // SMTPfast sends one event per request
  const event = req.body;
  switch (event.type) {
    case "delivered": // ...
    case "bounced": // ...
  }
  res.sendStatus(200);
});

Step 7: Test in Parallel

Before cutting over completely, run both providers in parallel for a few days:

async function sendEmail(to, subject, html) {
  // Send via SMTPfast
  const smtpfastResult = await fetch("https://smtpfa.st/api/v1/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ from: "[email protected]", to, subject, html }),
  });

  if (!smtpfastResult.ok) {
    // Fall back to SendGrid during migration
    console.error("SMTPfast failed, falling back to SendGrid");
    await sgMail.send({ to, from: "[email protected]", subject, html });
  }
}

Once you are confident SMTPfast is delivering reliably, remove the SendGrid fallback.

Step 8: Clean Up

After the migration is complete:

  1. Remove the SendGrid SDK from your dependencies
  2. Delete the SENDGRID_API_KEY environment variable
  3. Remove SendGrid's SPF include from your DNS
  4. Revoke your SendGrid API keys
  5. Cancel your SendGrid plan

Migration Checklist

  • SMTPfast account created
  • Sending domain added and verified
  • DNS records configured (DKIM, SPF, DMARC)
  • API key generated and stored securely
  • Code updated to use SMTPfast API
  • Webhooks reconfigured
  • Parallel testing completed
  • SendGrid fallback removed
  • SendGrid dependencies removed
  • SendGrid API keys revoked
  • SendGrid SPF include removed from DNS

Ready to get started?

Start sending transactional email today. Free to start, no credit card required.

Get Started for Free