All dispatchesView as Markdown

How to A/B test email service providers without fooling yourself

MC
Maya ChenEmail infrastructure at Email Bump

A rigorous guide to ESP evaluation: experimental design, reputation confounders, delivery and latency metrics, webhook reliability, failover, cost, and migration.

Comparing email service providers sounds like a familiar A/B test: route half of your messages through Provider A, half through Provider B, and pick the one with more opens. In practice, that design can confidently select the wrong provider.

An ESP changes infrastructure, IP history, authenticated domains, queue behavior, retries, feedback classification, tracking, link domains, webhook delivery, and operational tooling. Inbox placement is private and receiver-specific. Opens are noisy. New identities may have no history. Unless the experiment controls those differences—or explicitly treats them as part of the product being tested—the result is difficult to interpret.

Controlled email service provider evaluation showing eligibility, blocked randomization, two provider routes, normalized events, and decision metrics
FIG.A defensible ESP test uses one eligible population, stable assignment within important cohorts, equivalent messages, and one normalized measurement layer.

Start with a decision, not a vendor bake-off

Write the decision the test must support. A transactional team may care most about time-to-acceptance, queue expiry, API idempotency, event latency, and incident response. A lifecycle team may prioritize segmentation, workflow controls, branded tracking, complaint handling, and operational usability. Finance may care about total cost at expected volume, not list price.

Example decision statement
DECISION
Choose the default provider for security and account email.

PRIMARY OUTCOME
Receiver acceptance within 60 seconds of application enqueue.

GUARDRAILS
Final failure, duplicate message, complaint, webhook loss, and support incident.

NON-NEGOTIABLES
Aligned DKIM, custom Return-Path, signed webhooks, idempotent API,
regional data requirement, suppression export, and documented retry behavior.

EVALUATION WINDOW
Long enough to include normal weekday, weekend, and traffic cycles.

Remove vendors that fail non-negotiable security, compliance, identity, volume, or integration requirements before exposing customer traffic. An experiment should choose between viable options, not rediscover that a provider lacks a required feature.

Choose what you are actually testing

01 / Transport comparisonEquivalent content and aligned domains through two providers

Attempts to isolate routing, queueing, IP pools, receiver handling, and event quality.

02 / Full-platform comparisonEach provider configured the way you would operate it in production

Includes editor, analytics, automation, support, defaults, and provider-specific identity choices.

03 / Migration validationCan the candidate reproduce current outcomes without breaking product state?

Focuses on parity, event semantics, suppressions, templates, and safe cutover.

04 / Resilience exerciseCan traffic fail over without duplicates or identity damage?

Tests your routing and state machine more than ordinary provider performance.

Document which differences are intentionally held constant and which belong to the treatment. If Provider B’s branded tracking, managed IP pool, or retry policy would be part of normal production use, removing it may produce a clean experiment that answers the wrong purchasing question.

Understand why ESP tests are easily confounded

A confounder affects the outcome and differs between test arms. Email has many. If Provider A receives established transactional traffic on a mature authenticated domain while Provider B receives a cold marketing subdomain and older recipients, you measured history and audience—not provider quality.

  • Mailbox-provider mix: Gmail, Microsoft, Yahoo, and corporate gateways react differently.
  • Message type: password resets, receipts, invitations, alerts, and promotions have different urgency and engagement.
  • Audience quality: recent customers and dormant imported contacts are not interchangeable.
  • Domain history: a mature DKIM domain and a new subdomain begin with different receiver evidence.
  • IP model: shared pools, dedicated IPs, and recycled or newly assigned addresses carry different histories.
  • Volume and timing: weekday cycles, launches, spikes, and batching affect queues and receiver throttling.
  • Authentication and links: DKIM, Return-Path, DMARC alignment, tracking, and redirect domains may differ.
  • Content rendering: template transformations can change HTML, plain text, headers, URLs, and message size.
  • Retry and expiry: one provider may keep attempting long after the message is no longer useful.
  • Measurement: providers define accepted, delivered, bounced, deferred, opened, and unique clicked differently.

Build one eligibility layer before routing

The application should decide whether a message is allowed and useful before provider assignment. Apply consent, suppression, destination, frequency, template, and idempotency rules once. Both test arms should receive messages from the same eligible population rather than provider-specific audience queries.

Routing boundary
EVENT
  → validate message purpose and required data
  → apply consent, suppression, frequency, and abuse policy
  → generate immutable application_message_id
  → assign experiment arm from stable unit
  → render canonical content and metadata
  → send through provider adapter
  → normalize provider events into shared outcome model

Never send both variants of a real transactional message to the same recipient merely to create paired observations. That creates duplicate receipts, alerts, or security links and changes recipient behavior. One eligible message gets one provider assignment.

Randomize a stable experimental unit

Choose the unit that can receive one treatment without contamination. For most customer email, assign at account, workspace, tenant, or recipient level so the same person does not switch providers on every message. Stable assignment simplifies attribution and prevents inconsistent thread, sender, and latency experiences.

Stable assignment
unit = workspace_id ?? account_id ?? recipient_id
stratum = receiver_family + message_type + region
bucket = hash(experiment_id + unit) % 10000

if bucket < allocation_a:
  provider = A
else:
  provider = B

Store:
experiment_id · unit · arm · assigned_at · eligibility_version

Do not hash an email address into logs or analytics without considering privacy and address changes. Prefer an internal stable identifier. Keep the experiment identifier in assignment so future tests do not inherit the same accidental split.

Block on the nuisance factors that matter most

Randomization balances unknown differences over enough observations. Blocking or stratification deliberately balances known nuisance factors. NIST summarizes the principle as blocking what you can and randomizing what you cannot. For ESP testing, receiver family and message type are usually the most important blocks.

Blocked allocation
WITHIN EACH COHORT, RANDOMIZE BETWEEN A AND B

Gmail × password reset       A 50% | B 50%
Gmail × receipt              A 50% | B 50%
Microsoft × password reset   A 50% | B 50%
Microsoft × receipt          A 50% | B 50%
Yahoo × receipt              A 50% | B 50%
Corporate/other × receipt    A 50% | B 50%

Also monitor region, hour, customer tier, and audience recency.
Do not create tiny strata that cannot produce useful evidence.

If randomization is impossible—for example, the candidate must use one entire subdomain—call the rollout a phased observational comparison, not an A/B test. Match traffic as carefully as possible, annotate identity age and volume changes, and make a more cautious causal claim.

Make authentication and identity comparable

Before live traffic, inspect actual messages from each provider. A control panel saying “verified” is insufficient. Confirm the visible From, MAIL FROM and Return-Path, DKIM d= and selector, SPF result, DMARC alignment, Message-ID, Reply-To, List-ID where applicable, unsubscribe headers, tracking host, and every redirect.

Identity parity check
                         PROVIDER A             PROVIDER B
Visible From domain      notify.example.com     notify.example.com
DKIM signing domain      notify.example.com     notify.example.com
SPF / Return-Path        bounce-a.example.com   bounce-b.example.com
DMARC alignment          pass                   pass
Tracking domain          click-a.example.com    click-b.example.com
Reply-To behavior        support mailbox        support mailbox
Message-ID uniqueness    application-linked     application-linked
TLS / PTR / HELO         verified route         verified route

Perfect identity equivalence may be impossible because two providers cannot both control the same Return-Path host and DKIM selector simultaneously. Use distinct aligned subdomains with comparable history and disclose the difference. Do not rotate one DNS record between providers during the test; propagation and caching turn assignment into guesswork.

Do not compare a mature route with an unwarmed dedicated IP

A dedicated IP offers control and responsibility, not automatic trust. If the candidate requires a new dedicated IP, establish legitimate, stable volume before interpreting placement and deferrals. If your volume is too low or irregular to maintain useful history, a well-managed shared pool may be the more appropriate production configuration and therefore the fairer test.

  • Ask how the provider assigns, retires, and potentially reuses dedicated IPs.
  • Confirm whether shared-pool placement is segmented by traffic quality and message type.
  • Monitor IP and authenticated-domain evidence together; neither explains every outcome alone.
  • Ramp with normal wanted traffic, not dormant contacts selected merely to create volume.
  • Avoid changing IP model, domain, audience, and content during the same evaluation window.

Create a provider-neutral event model

Provider dashboards are useful for operations but poor foundations for comparison because event names and state transitions differ. Normalize both streams into one warehouse or application schema while retaining raw payloads.

Canonical delivery event
application_message_id   Immutable ID created before provider routing
provider_message_id      Provider-specific lookup ID
experiment / arm         Assignment and treatment metadata
event_id                 Provider event ID for deduplication
state                    enqueued · attempted · deferred · accepted · failed · expired
occurred_at               Provider event time
received_at               Your webhook receipt time
smtp_reply                Basic SMTP response
status_code               Enhanced status code when available
raw_diagnostic            Unmodified receiver text
receiver_family           Gmail · Microsoft · Yahoo · corporate · other
attempt                   Attempt sequence
stream / template         Purpose and content version
recipient_id              Internal stable unit
raw_payload_pointer       Auditable original event
  • Verify webhook signatures or authentication before processing events.
  • Deduplicate repeated deliveries and tolerate out-of-order events.
  • Do not let a late deferred event overwrite a later final acceptance or failure.
  • Measure provider event time and your receipt time separately.
  • Retain raw diagnostics because normalized bounce taxonomies hide useful receiver detail.
  • Reconcile provider totals against application enqueue counts and unresolved states.

Measure the transport before engagement

An ESP’s “delivered” event usually means a receiving SMTP server accepted responsibility for the message. It does not prove inbox placement, display, reading, or human action. Start with transport outcomes the provider can observe directly.

Transport scorecard
METRIC                              DEFINITION
API availability                    Successful valid requests / attempted requests
API response latency                Client request → provider acknowledgement
Time to first attempt               Enqueued → first SMTP attempt
Time to receiver acceptance         Enqueued → final 2.x.x acceptance
Acceptance within product SLO       Accepted before message-specific deadline
Temporary deferral rate             Unique recipients with active 4xx state
Final failure rate                  Terminal failure / eligible messages
Classification accuracy             Sampled diagnostic matches normalized category
Duplicate message rate              Recipients receiving same logical event twice
Webhook lag                         Provider event → authenticated receipt
Unresolved state rate               Enqueued messages without valid final/current state

Report latency distributions, not only averages. Password-reset experience is shaped by the slow tail, so inspect median, p95, and p99 by receiver and message type. Define whether the clock starts at the application event, queue insertion, API request, or provider acceptance and use the same boundary for both arms.

Treat inbox placement as estimated evidence

Neither provider can log into every customer mailbox. Seed tests can show where controlled messages appear in a panel of accounts, and provider dashboards can reveal receiver-specific reputation, complaints, authentication, and errors. Both are useful directional evidence with coverage limits.

  • Use the same seed accounts, message content, time window, and identity treatment for both providers.
  • Review trends and receiver-specific differences rather than treating one seed percentage as truth.
  • Exclude broken or stale seed accounts and document panel changes.
  • Correlate placement with SMTP responses, provider dashboards, and real customer outcomes.
  • Do not call Gmail Promotions a delivery failure when that placement is expected for the message.
  • Keep test messages out of customer metrics and avoid artificial traffic intended to manipulate reputation.

Use engagement as a downstream outcome, carefully

Clicks, replies, conversions, and product events can reveal whether accepted mail led to value. Opens are incomplete and can be inflated by privacy or security systems; clicks can be generated by scanners. Provider-specific tracking can also change URLs, redirects, cookies, and event filtering, making dashboard numbers incomparable.

Outcome hierarchy
TRANSPORT       Receiver accepted before usefulness deadline
PLACEMENT       Directional inbox/spam evidence for controlled accounts
INTERACTION     Human-quality click or reply
PRODUCT VALUE   Password reset completed, invoice viewed, account activated
NEGATIVE        Complaint, unsubscribe, support issue, duplicate, security alert

Primary example:
verified_reset_completions_within_10_minutes / eligible_reset_events

Measure product outcomes from your application, not only ESP redirects. Keep content, CTA destination, attribution window, and bot filtering equivalent. If one provider’s tracking is the feature under evaluation, report both its native numbers and an independent product event.

Predefine the analysis before looking at results

State the primary metric, experimental unit, strata, allocation, minimum detectable effect, sample requirement, evaluation window, exclusions, guardrails, and stopping rule. This prevents a team from choosing whichever metric favors its preferred vendor after the fact.

  • Calculate sample needs from the baseline rate and smallest operationally meaningful difference.
  • Use confidence intervals around the treatment difference, not only a winner label.
  • Analyze at the randomization unit; repeated messages to one account are not independent customers.
  • Report predeclared receiver and message-type strata before exploring smaller slices.
  • Avoid checking each day and stopping the first time one arm looks significant.
  • Annotate outages, DNS edits, template changes, imports, launches, and audience-policy changes.
  • Treat rare severe failures as guardrails even when the primary metric improves.

Test webhook and event reliability under stress

A provider can deliver mail well and still create an unreliable product integration. Exercise duplicate webhooks, delayed delivery, out-of-order events, endpoint timeouts, signature failure, payload changes, retry exhaustion, and recovery after your endpoint is unavailable.

Webhook reliability exercise
1. Accept event and verify signature
2. Return the documented success response quickly
3. Process asynchronously with an idempotent event key
4. Make the endpoint unavailable for a controlled interval
5. Confirm provider retry cadence and retention
6. Restore endpoint and reconcile all expected events
7. Deliver duplicates and reordered states intentionally
8. Verify final application state and alerting
9. Replay retained raw payloads through a parser upgrade

Run this in a sandbox or carefully isolated test stream when possible. Never break a production webhook without a recovery plan, defined window, and authorization. Ask how long the provider retains events and messages, how replay works, and whether support can recover data after your endpoint fails.

Test failover without double-sending

Multi-provider failover is not “if API A times out, call API B.” A timeout can happen after Provider A accepted the message, leaving its state unknown. Sending immediately through B may produce two password resets, receipts, or alerts.

Safe failover state machine
CREATED
  → attempt provider A with idempotency key
  → accepted: record A message ID; never submit to B
  → explicit pre-accept rejection: eligible for controlled B route
  → timeout / unknown: reconcile A before deciding
  → provider-wide incident: open circuit for new messages
  → route newly eligible messages to B with same application ID

At every step:
One logical event · one active provider owner · auditable state transition

The backup route also needs warmed, authenticated, monitored identities and current suppressions. A dormant emergency provider introduced only during an incident may be the least trusted route at the worst moment.

Compare operational quality, not only delivery

The provider your team can operate safely often beats the provider with a marginal dashboard advantage. Evaluate documentation, SDK behavior, template versioning, permissions, audit logs, API-key scopes, suppression semantics, data export, incident communication, status history, support escalation, and change management.

Weighted decision scorecard
CATEGORY                     WEIGHT   A SCORE   B SCORE   EVIDENCE
Delivery and latency           25%      4.2       4.5       Experiment
Reliability and event integrity 20%     4.6       3.8       Failure drills
Security and compliance        15%      pass      pass      Review
Deliverability operations      15%      4.0       4.4       Tools/support
Developer experience           10%      3.7       4.6       Implementation
Lifecycle/product workflow     10%      4.5       3.5       Team trial
Total operating cost            5%      3.9       4.1       Forecast

Non-negotiable failure overrides the weighted total.

Agree on weights before results. Attach evidence to every score and distinguish measured behavior from sales claims. A scorecard makes tradeoffs visible; it does not turn subjective guesses into objective truth.

Calculate total cost around useful outcomes

List price omits engineering work, add-ons, dedicated IPs, support tiers, data retention, validation, inbound processing, analytics, overages, migration, compliance review, and incident burden. Compare cost at expected and stress volumes.

Cost views
MONTHLY PLATFORM COST
subscription + sends + contacts + add-ons + support + IPs

OPERATING COST
platform + engineering + deliverability + support + incident time

COST PER TIMELY ACCEPTED MESSAGE
operating cost / messages accepted before product deadline

COST PER VERIFIED PRODUCT OUTCOME
operating cost / independently measured successful outcomes

Do not monetize complaints, security failures, or duplicate critical messages into an average. Some outcomes are constraints. A cheaper provider that violates a customer or regulatory requirement is not a bargain.

Run the evaluation in controlled stages

Evaluation sequence
1. PAPER REVIEW     Non-negotiables, architecture, data, security, cost
2. INTEGRATION LAB   API, identity, templates, webhooks, suppression, exports
3. SYNTHETIC TRAFFIC Internal and controlled accounts; failure injection
4. LIMITED LIVE      Small wanted cohort with stable randomized assignment
5. BALANCED TEST     Blocked allocation across receiver and message type
6. STRESS WINDOW     Expected peaks, queue behavior, rate limits, support
7. DECISION          Predeclared analysis, scorecard, risks, owner sign-off
8. MIGRATION         Phased cutover, rollback gates, reconciliation
9. POST-CUTOVER      Outcome, reputation, cost, and event-integrity review

Allocation does not need to begin at 50/50. Start at the smallest level that can reveal integration failures without creating a noisy statistical conclusion. Increase only after authentication, event reconciliation, latency, failure classification, and customer guardrails remain healthy.

Plan migration as a separate production change

Winning an experiment does not authorize an instant full cutover. Export and preserve suppressions, map template versions, verify every domain, reconcile event semantics, train support, update incident runbooks, establish dashboards, and define rollback before increasing allocation.

  • Freeze unrelated identity and template changes around the cutover.
  • Maintain one source of truth for consent and suppression across both providers.
  • Prevent contacts from receiving duplicates when segments or queues overlap.
  • Keep historical provider IDs and raw events available for support and audits.
  • Monitor authenticated-domain and IP reputation by receiver throughout the transition.
  • Define rollback gates using customer outcomes and event integrity, not only API uptime.
  • Retire old credentials, webhooks, DNS, and data only after retention obligations and reconciliation are complete.

Common ESP-comparison mistakes

  • Calling a before-and-after migration an A/B test while audience, season, identity, and volume all changed.
  • Comparing opens from two providers with different tracking and bot filtering.
  • Treating receiver acceptance as proof of inbox placement.
  • Sending the same transactional event through both providers to create paired results.
  • Assigning recent active users to one arm and dormant recipients to the other.
  • Comparing a mature route with a cold domain or newly assigned dedicated IP.
  • Ignoring mailbox-provider and message-type mix in the analysis.
  • Using provider dashboard labels without a shared event model.
  • Failing over after an ambiguous timeout and creating duplicate messages.
  • Choosing on delivery alone while ignoring webhook loss, support, security, exports, and operating cost.
  • Stopping as soon as a preferred provider leads on one metric.
  • Migrating every stream immediately after a limited test.

ESP evaluation checklist

  • Define the purchasing decision, treatment, primary outcome, guardrails, and non-negotiables.
  • Choose a stable experimental unit and assign one logical message to one provider.
  • Block allocation by receiver family and message type; monitor other important cohorts.
  • Keep eligibility, content, timing, identity, and measurement as comparable as the treatment allows.
  • Verify SPF, DKIM, DMARC alignment, Return-Path, tracking, headers, TLS, PTR, and redirects from real messages.
  • Account for domain and IP history instead of calling a cold identity neutral.
  • Normalize provider events while retaining raw payloads and diagnostics.
  • Measure latency distributions, acceptance before deadline, deferrals, final failures, duplicates, and webhook integrity.
  • Treat placement tests as directional and measure product outcomes independently.
  • Predefine sample, analysis, confidence reporting, evaluation window, exclusions, and stopping rules.
  • Exercise webhook recovery and failover state without risking customer duplicates.
  • Score security, operations, support, developer experience, workflow, and total cost alongside delivery.
  • Use a phased migration with suppression parity, reconciliation, rollback gates, and post-cutover review.