Marketing

Choosing a Transactional Email Provider

Antonio Evans8 min read

A split-scene illustration: on the left, a server rack labeled 'App' sending envelopes through a pipe; in the middle, a control panel showing gauges for 'Deliverability', 'Webhook Health'.
Key points

Key points

  1. 1Compare deliverability history, the webhook contract, and bounce handling before you compare price per thousand.
  2. 2Ask for blocklist history and complaint-rate data, and check that your sending is authenticated and segregated from marketing streams.
  3. 3Test retries, idempotency, signatures and dead-letter handling by injecting failures in a sandbox, not by reading docs.
  4. 4Read the exact suppression rules for hard bounces, soft bounces and complaints, then decide who owns the suppression list.

Start with the inbox, not the invoice

Transactional email is the mail your product cannot afford to lose: password resets, receipts, two-factor codes, shipping notices. A lost receipt costs a support ticket. A lost password reset costs a customer. Price per thousand matters, but only after you know the message will arrive, that the provider will tell you the truth about failures, and that its bounce rules will not quietly delete your ability to reach a real person.

The mailbox providers have made the baseline public. Gmail requires SPF or DKIM from all senders and, for anyone sending 5,000 or more messages a day to personal Gmail accounts, SPF, DKIM and DMARC, a spam rate below 0.3%, one-click unsubscribe on marketing and subscribed messages, and valid forward and reverse DNS records (Gmail sender guidelines). Yahoo publishes the same 0.3% ceiling and the same authentication expectations (Yahoo Sender Hub). None of this is negotiable with your provider. What you are really buying is a partner that keeps you inside those lines and tells you when you drift.

The order of checks below is deliberate. Each one is cheap to run and can eliminate a provider before you spend time on a migration. A provider that fails any of the three will not be rescued by a low rate.

Check 1: the deliverability track record

Two senders with identical code get different results depending on the IP their mail leaves from. A shared IP pools the reputation of every sender on it, and one bad sender can drag the pool down through greylisting or blocklisting (Mailtrap on shared versus dedicated IPs). Postmark recommends sending at least 300,000 messages a month before a dedicated IP can be maintained well, because infrequent or spiky volume on a dedicated IP looks like spam behavior to inbox providers (Postmark's dedicated versus shared IP guide). If your transactional volume is a few hundred a day, a dedicated IP is usually the wrong purchase, and a provider that pushes one hard is telling you something about how it segments customers.

Question to askGood answer looks likeRed flag
Which IP pool will we land on, and who else is in it?Named pool, onboarding that reviews your volume and content"We will figure it out after signup"
Is transactional mail segregated from marketing?Separate IPs or DKIM domains per streamOne stream for everything
What is your blocklist monitoring process?Proactive checks, alerts, published removal procedureReactive only, on your complaint
Can we see historical blocklist events for our pool?Data provided under NDA or in a pilot reportRefusal to discuss history
Which authentication do you support out of the box?SPF and DKIM self-serve, DMARC alignment guidanceManual records you maintain yourself

Yahoo's guidance is explicit that bulk and marketing mail should not go out from the same IPs as transactional and user mail, because each IP and DKIM domain carries its own reputation (Yahoo Sender Hub). Ask your provider to show you the separation, not just describe it. DMARC is what ties authentication back to the domain your recipient sees, and alignment is the part that fails quietly when a third party rewrites the Return-Path or signs with its own domain (Adaptive Security on DMARC alignment). A provider that sends on your behalf without clear alignment guidance will cost you inbox placement.

Two practical checks you can run before signing anything:

  1. Send a test batch through the provider to seed accounts at Gmail, Outlook and Yahoo, and read the raw headers. Confirm the Return-Path domain, the DKIM signing domain and the From domain align under your DMARC policy.
  2. Look up the sending IPs and your domain in public blocklist checkers, and repeat the check weekly during the pilot.

If you want to watch complaint signals during the pilot, Gmail's Postmaster Tools gives you a compliance status view and a spam rate line; treat 0.1% as the point where you pause and investigate and 0.3% as an incident, since the dashboard measures manual reports on inbox-delivered mail only, not every filtered message (Suped on Postmaster Tools spam rate).

Check 2: the webhook contract

Every provider promises webhooks for delivered, bounced, complained and opened events. The differences live in the fine print, and they show up at the worst possible time: a delivery event lost during a deploy, a duplicate that sends your customer two "your order shipped" emails, or a bounce you never receive because the retry window closed overnight.

Webhooks are POST requests, and most providers operate on an at-least-once guarantee, meaning duplicates are normal and your handler has to be idempotent (Hookdeck on webhook idempotency). Because POST implies side effects, the burden of making the endpoint safe falls on you, usually through a unique constraint on an event ID or a processed-events table.

Ask each provider these five questions, and write the answers into your integration design:

Contract itemWhat to confirm
RetriesHow many attempts, over what window, with what backoff
IdempotencyIs there a stable event ID in the payload or headers
OrderingAre events per message ordered, or must you sort by timestamp
SignaturesWhich header carries the signature, which algorithm, key rotation
Dead lettersWhere failed events go after retries, and how you replay them

A common pattern is exponential backoff with a capped number of attempts, often three to five, plus logging of failed requests so you can troubleshoot (2Point on retries and idempotency keys). If your provider retries for 24 hours and yours does not, a two-hour outage in your own infrastructure means permanently lost delivery data. That is a decision rule worth stating plainly: choose a retry window at least as long as your worst realistic outage, and choose a dead-letter path for everything beyond it.

Here is a minimal idempotent handler that turns a duplicate delivery into a no-op:

import psycopg

def handle_event(event_id: str, payload: dict, db: psycopg.Connection) -> bool:
    try:
        with db.cursor() as cur:
            cur.execute(
                "INSERT INTO processed_webhooks (id) VALUES (%s)", (event_id,)
            )
    except psycopg.errors.UniqueViolation:
        db.rollback()
        return True  # already processed, acknowledge and move on
    try:
        apply_delivery_status(payload)
        db.commit()
        return True
    except Exception:
        db.rollback()
        with db.cursor() as cur:
            cur.execute("DELETE FROM processed_webhooks WHERE id = %s", (event_id,))
        db.commit()
        raise

The delete-on-failure step matters. Without it, a handler that crashes mid-processing records the event as seen and silently swallows the retry (Hookdeck).

Test all of this with failure injection during the pilot. Point the webhook at an endpoint that returns 500 for the first two attempts, then 200. Point it at an endpoint that sleeps past the provider's timeout. Send the same event twice and confirm your database shows one shipment email, not two. Verify signatures by replaying a captured request with a tampered body and confirming your code rejects it. If the provider cannot give you a sandbox with controllable failure modes, that is a finding, and you should write it down next to the price.

Check 3: bounce and complaint handling

This is where providers diverge most and where the cheapest option often costs the most. A hard bounce is a permanent failure: the mailbox does not exist. A soft bounce is temporary: a full mailbox, a greylisting delay, a server outage. Providers that treat soft bounces like hard bounces will suppress real customers who had a full inbox on a Tuesday, and those customers will not get their password reset. Ask directly how many soft bounces trigger suppression and over what period.

Suppression rules are the part you must read line by line. Yahoo requires senders to honor unsubscribes within two days and recommends the one-click Post method in the list-unsubscribe header (Yahoo Sender Hub). Google requires one-click unsubscribe for marketing and subscribed messages from bulk senders, with a visible unsubscribe link in the body (Gmail sender guidelines). For transactional mail the compliance bar differs, but complaint handling still applies: a recipient who hits "report spam" on a receipt has told the mailbox provider something about you.

Feedback loops are how you hear about complaints. Gmail's Postmaster Tools and Yahoo's complaint feedback loop are the two you will actually use, and both feed the 0.3% number that gets senders rejected (MxToolbox on the Gmail and Yahoo requirements). Confirm that your provider enrolls your domain in both, passes the complaint data to your webhook, and applies its own suppression on top.

Then get the ownership question in writing:

  • Who owns the suppression list, you or the provider? If you migrate, does it come with you?
  • Are hard bounces suppressed on first occurrence, and are they visible in an export?
  • What complaint rate triggers an account review or a sending pause, and who is notified?
  • Can you override a suppression for a verified, opted-in address, and is that logged?
  • Do you get bounce and complaint reasons in a machine-readable field, or only in a dashboard?

List hygiene compounds all of this. Bounce rates of even 0.5% can trigger scrutiny from inbox providers, and on a shared IP a handful of bad addresses affects every other sender on the pool (Mailtester on low-volume transactional sending). Verify addresses at signup rather than cleaning lists later, and treat the suppression list as a product asset you own.

Run a pilot before you sign

You can complete the three checks in about two weeks with a small script and a seed list. Run your real templates, not lorem ipsum, because content filters respond to structure and links. Send to seed accounts at the major consumer domains, inject webhook failures, and push a deliberate hard bounce to watch the suppression fire.

Score the results on the dimensions that will actually hurt you:

DimensionWhat you measureWhy it decides the contract
AuthenticationAlignment pass rate on seeded sendsMisalignment is a silent, permanent failure
IP setupPool segregation, blocklist events during pilotReputation you inherit without choosing it
RetriesEvents recovered after injected 500sYour outage tolerance
DuplicatesShipment emails after a replayed eventCustomer-visible damage
SuppressionHard and soft bounce behaviorDeliverability you can lose by accident
Complaint pathFeedback loop enrollment, data in webhooksEarly warning before rejection

Only after those six hold up should cost per thousand enter the comparison, and even then compare the total: per-message rate, dedicated IP fees, overage charges, and the engineering hours your team spends on retries and reconciliation. A provider that saves you a fraction of a cent per message but returns duplicates or drops delivery events will cost more in support tickets and lost trust.

Where this lands in your stack

Most teams discover they need an internal service, not just an API key. A small sending service that owns templates, retries, idempotency and the suppression mirror gives you a single place to swap providers if the pilot data turns against one. That service is also where you centralize the operational tooling around email: delivery dashboards, bounce reports and incident runbooks. If you would rather have a specialist build that service and the surrounding tooling with you, Quanta (https://quantaintelligence.ai/) takes a description of the app or service you need and pairs you with someone who builds it alongside you.

Whatever you build, keep the raw events. Store delivery, bounce and complaint payloads for at least as long as your longest support dispute window, because the provider's dashboard retention is rarely the same as yours.

FAQ

FAQ

How many emails a day make me a bulk sender?

Gmail defines a bulk sender as any sender reaching close to 5,000 messages or more to personal Gmail accounts in 24 hours, counting all messages from the same primary domain, and the classification is permanent once applied (Gmail sender guidelines FAQ). Yahoo applies similar expectations to bulk senders. Below that threshold the authentication basics still apply to all senders.

Can I use my marketing provider for transactional email?

You can, but segregation is recommended: Yahoo advises against sending bulk or marketing mail from the same IPs as transactional and user mail, because reputation is tracked per IP and per DKIM domain (Yahoo Sender Hub). If a promotional campaign spikes complaints, your password resets inherit the consequences. Use separate streams even if you use one vendor.

What exactly should DMARC policy be set to?

Start at p=none to collect reports, then move to quarantine and eventually reject once your sending sources are inventoried and aligned. A DMARC record tells receivers what to do with mail that fails SPF or DKIM, with options of none, quarantine or reject (Google Workspace DMARC setup). The record is only as good as the alignment behind it.

How do I know a webhook was delivered exactly once?

You cannot guarantee exactly once; most providers guarantee at least once. Build your handler so a second delivery of the same event is a no-op, using a unique event ID and a processed-events table, and return a success status on the duplicate (Hookdeck). Test it by replaying a real captured event twice.

Should I get a dedicated IP for low-volume transactional email?

Usually no. Postmark recommends at least 300,000 messages a month before a dedicated IP can be maintained properly, because inconsistent volume on your own IP looks suspicious to inbox providers (Postmark). At low volume, a shared pool with a provider that segments customers well is the safer default, provided you have verified your addresses and can see blocklist events.

Sources

Sources

  1. Email sender guidelines - Gmail Help
  2. Sender Best Practices - Yahoo Sender Hub
  3. Shared vs Dedicated IP in Email Sending 2026
  4. Dedicated vs. shared IPs for email: when to use each?
  5. What Is DMARC Alignment? SPF, DKIM, and Strict Modes
  6. Understanding Google Postmaster Tools V2 Spam Rate ...
  7. How to Implement Webhook Idempotency - Hookdeck
  8. Webhook Retries and Idempotency Keys - Best Digital Marketing Agency
  9. New Gmail & Yahoo Sender Requirements - What are they?
  10. Dedicated IP vs Shared IP for Low Volume Transactional ...
  11. Email sender guidelines FAQ - Gmail Help
  12. Set up DMARC | Security & data protection
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles