Switching from Postmark, ErrorCodes intact
Postmark integrations lean on semantics — ErrorCode 0, the 406 inactive recipient, batch always answering 200 per-message. Those survive the switch. This page is precise about what does not.
Facts verified 2026-08-29 — corrections: hello@emailfast.dev
Keep the semantics you built on
import { ServerClient } from "postmark";
- const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN);
+ const client = new ServerClient(process.env.EMAILFAST_API_KEY, {
+ requestHost: "api.emailfast.dev", // ef_sandbox_… works everywhere
+ });That's the code change, because SendGrid-, Mailgun-, and Postmark-compatible endpoints: point your existing SDK at a new base URL with a new key and keep your code — attachment sends are the one exception, refused with a clear error in your provider's own format rather than silently dropped. What the Postmark-compatible endpoints honor, verified against the code that serves them:
POST /emailandPOST /email/batch, same shape, with your Email Fast key in theX-Postmark-Server-Tokenheader.- ErrorCode semantics preserved:
0on success with aMessageID, 406 for an inactive (suppressed) recipient, 300 for a blocked send. A failing single send answers HTTP 422 with the ErrorCode in the body — real wire parity, so the officialpostmarknpm client's typed errors work against it. CcandBcccarry over to every message fanned from a comma-separatedTo, with native guardrails: per-recipient suppression and quota, the same 50-recipient cap Postmark enforces, and BCC never appearing in a header.- Batch behaves like Postmark's batch: always HTTP 200, one result per message, so a partial batch reads exactly the way your code already handles it — each element independently succeeds or fails.
- Attachments are refused loudly. Outbound attachments aren't supported yet, platform-wide; a send carrying one answers HTTP 422 with ErrorCode 300 and a message saying so — never a message quietly delivered without its file.
Headers,Metadata, andInlineCssare accepted without effect. (Postmark's API has no scheduling field, so nothing arrives and nothing is dropped.) - Retries can be made idempotent with an
Idempotency-Keyheader, per recipient: a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.
And the same admission discipline Postmark users switch providers to keep applies to every ingress here: every send — REST, SMTP, browser SDK, compatibility endpoints, broadcasts, automations — passes through one admission gate: idempotency, suppression, quota, and content policy in a single checkpoint no ingress can skip.
What moves by hand — said plainly
There is no hosted Postmark importer. The planned import lane covers SendGrid, Mailgun, and Mailchimp; Postmark templates and layouts are re-created in the dashboard or over POST /v1/templates — slug each with its old TemplateId or alias so existing template sends resolve unchanged. Suppression lists export from Postmark as CSV and import here as suppressions — do that before your first send so old bounces and unsubscribes stay honored.
| What you're moving | The work | Time |
|---|---|---|
Send calls (postmark package or raw HTTP) | Request host + token, then a sandbox test | Under an hour |
| Domain verification | SPF/DKIM records at your DNS host | Minutes of work, propagation up to a few hours |
| Templates and layouts | Re-created by hand, slugged with old ids so TemplateId sends keep working — no importer for Postmark | An afternoon for a handful; more with heavy layout use |
| Suppression lists | CSV export → suppression import, before first send | Under an hour |
All of it runs dry first: sandbox keys (ef_sandbox_…) that run the real pipeline dry: real validation, real rendering, real events, a hosted capture inbox — and no email leaves.
What Postmark publishes at your volume
Postmark deserves credit for publishing exact calculator ticks rather than "starting at" prices — the table below is their own published points, not our interpolation.
| Monthly emails | Price / month | Published as |
|---|---|---|
| 10,000 | $15 | Basic tier |
| 50,000 | $55 | Basic tier |
| 125,000 | $115 | Basic tier |
| 300,000 | $245 | Basic tier |
| 700,000 | $455 | Basic tier |
| 1,500,000 | $775 | Basic tier |
Detail: Free developer tier: 100 emails/month, never expires. Calculator slider snaps to fixed ticks only: 10k/50k/125k/300k/700k/1.5M (no 100k or 500k stop) - 100k and 500k figures below use the smallest published tier that covers the volume. Three feature levels at every volume: Basic, Pro (+10%, e.g. $16.50 at 10k), Platform (+20%, $18.00 at 10k). Overage per 1,000 extra: Basic $1.80 ($1.70 at >=300k), Pro $1.30 ($1.25), Platform $1.20 ($1.15). Monthly billing only (no annual plans offered).
Not published / not verified: Exact 100k and 500k prices (calculator has no stop at those volumes).
Figures verified 2026-08-29 on the Postmark (ActiveCampaign) pricing page, promo and intro discounts excluded — method and corrections via the claims methodology.
Price your own volume: 10,000 sends/month, 125,000, or 700,000.
Where Email Fast stands
| Plan | Price / month | Emails included | Overage per 1,000 |
|---|---|---|---|
| Free | $0 | 2,500 | — |
| Starter | $9.90 | 20,000 | $0.90 |
| Creator | $39 | 100,000 | $0.65 |
| Growth | $79 | 300,000 | $0.55 |
| Scale | $249 | 1,500,000 | $0.35 |
Our stake, declared: we make Email Fast, and these are the launch prices already published on our pricing page — during early access they may be refined before general availability, and self-serve checkout opens at GA. Contacts and subscribers are never billed, at any list size.
Where Postmark wins
From our own pricing survey, their side stated plainly — Best-in-class transactional deliverability reputation and delivery speed (separate transactional/broadcast message streams), superb developer experience, and a free tier that never expires.
Honest additions: a transactional reputation earned over many years is not a thing a new platform can claim to match — ours has to be earned the same way. If Postmark isn't hurting you on price or missing a feature you need, staying is a defensible choice. The full comparison: Postmark vs Email Fast.
Next
- The step-by-step migration guide
- Also pricing SendGrid or Mailgun?
- Suspended by your current platform? Read that first.
- Apply for early access — live sending starts by application
Postmark is a trademark of its owner; Email Fast is not affiliated with or endorsed by them. Postmark facts were verified on their public pages on the dates shown — corrections: hello@emailfast.dev.
Questions, answered plainly
Does my Postmark retry and suppression code keep working?
Yes — that's the point of the compatible surface: SendGrid-, Mailgun-, and Postmark-compatible endpoints: point your existing SDK at a new base URL with a new key and keep your code — attachment sends are the one exception, refused with a clear error in your provider's own format rather than silently dropped. Success returns ErrorCode: 0 with a MessageID; a failing single send answers HTTP 422 with the ErrorCode in the body — 406 for a suppressed recipient, 300 for a blocked send — which is Postmark's real wire behavior, so the official postmark npm client's typed-error handling keeps working; and /email/batch always answers HTTP 200 with a per-message result array, exactly as Postmark does.
Do my Postmark templates and layouts come across?
By hand, honestly. There is no hosted Postmark importer — the planned importers cover SendGrid, Mailgun, and Mailchimp — so templates are re-created in the dashboard or over POST /v1/templates. One bridge does work today: give the re-created template a slug equal to your old TemplateId or alias, and existing TemplateId/TemplateAlias sends resolve to it unchanged. Budget an afternoon for a typical set, more if you use layouts heavily.
Does Email Fast have separate transactional and broadcast streams?
Sends carry a message stream, and suppressions are stream-aware — a newsletter unsubscribe doesn't block a password reset. Postmark's strict stream separation is still the deeper implementation of the idea, and it's listed in their wins on this page for that reason.
How long does the switch take?
Send calls: under an hour — change the request host, put your Email Fast key in X-Postmark-Server-Token, run a sandbox test. Domain verification adds DNS time. Templates are the manual part: an afternoon for a handful, re-created rather than imported.