Migration guide
Migrate from SendGrid to Volanea.
Most SendGrid migrations are motivated by the retired free tier or the split between the transactional API and the separately-priced Marketing Campaigns product. Volanea folds both into one API — here's the mechanical part.
Undecided? Read the honest Volanea vs SendGrid comparison first.
Create the project and verify your domain
Sign up (free, no card), add your sending domain, and install the DKIM/SPF records Volanea shows you — fresh records, separate from SendGrid's. Keep SendGrid live for now: nothing gaps while DNS propagates, and verification is one click once it does.
Swap the send call
This is the heart of it — one call replaced by one call. Grab your secret key from project settings first.
before — @sendgrid/mail
import sgMail from "@sendgrid/mail";
sgMail.setApiKey(process.env.SENDGRID_API_KEY!);
await sgMail.send({
from: "shop@yourdomain.com",
to: "ada@example.com",
subject: "Your order shipped",
html: "<p>On its way, Ada.</p>",
});after — volanea
// npm i @volanea/sdk (or plain fetch — it's one POST)
import { Volanea } from "@volanea/sdk";
const volanea = new Volanea({ apiKey: process.env.VOLANEA_SECRET_KEY! });
await volanea.send(
{
to: "ada@example.com",
subject: "Your order shipped",
html: "<p>On its way, {{firstName}}.</p>",
variables: { firstName: "Ada" },
},
{ idempotencyKey: "order-4921" }, // retries become safe replays
);- SendGrid's dynamic template data maps to Volanea's variables — {{firstName}} style placeholders render server-side.
- Idempotency comes via the Idempotency-Key header (SendGrid has no equivalent — retries there risk duplicates).
- One key model instead of scoped keys: the secret key is server-side-only; a separate public key exists just for event ingestion.
Bring your contacts
Export your list from SendGrid as CSV and import it in the Volanea dashboard (or POST /v1/contacts/import). Columns map by header, imports run as a background job with live progress, and re-runs dedupe by email — a partial import is never a disaster. Unsubscribed contacts keep their status, so nobody who opted out gets mailed by mistake.
Re-point your webhooks
Register your endpoint in Volanea (the response includes the whsec_… signing secret), then translate the event names your handler listens for:
| SendGrid | Volanea |
|---|---|
| processed | email.sent |
| delivered | email.delivered |
| open | email.opened |
| click | email.clicked |
| bounce | email.bounced |
| spamreport | email.complained |
| dropped | email.failed |
Every delivery is HMAC-signed in the X-Volanea-Signature header and retried with backoff for ~24 hours — the docs include a drop-in verifier.
Test, then flip
Send through your test key (sk_test_…) first — messages render and log fully but deliver nothing, so you can assert on the whole pipeline in CI. When the domain is verified and the test sends look right, swap in the live key, watch the first real sends land in the dashboard, and retire the SendGrid credentials.
Watch for the gotchas
- SendGrid's Event Webhook batches events into arrays; Volanea delivers one signed event per request — simpler handlers, but adjust any batch-shaped parsing.
- Marketing Campaigns contacts export as CSV from the SendGrid UI — Volanea's importer maps columns by header and dedupes by email.
- If you relied on SendGrid's IP warmup / dedicated IPs, note Volanea uses shared infrastructure — fine at small/mid volume, a real consideration at 100k+/month.