Engineering
10 min read

15 Years of Shipping Software Taught Me Email Deliverability is an Infrastructure Problem

Why developers treat email as an afterthought and what goes wrong at scale. IP warming, feedback loops, bounce handling, reputation management, and the architecture of a reliable email pipeline.

Transactional Team
Feb 5, 2026
10 min read
Share
15 Years of Shipping Software Taught Me Email Deliverability is an Infrastructure Problem

The 37% Problem

Consider a common scenario: a SaaS product launches, and three months later the team discovers that 37% of transactional emails are not reaching inboxes. Password resets, invoice receipts, shipping confirmations -- over a third are landing in spam folders or being silently dropped.

The team is using a well-known email API. SPF and DKIM are configured. Email seems like a solved problem. It is not.

Email deliverability is an infrastructure problem masquerading as a feature checkbox. Most developers treat it as "call the API, email gets delivered." The reality is a complex system of reputation scoring, feedback loops, rate limiting, and protocol compliance that determines whether your email reaches the inbox, the spam folder, or the void.

Inbox Placement Rate by Authentication Level

No Auth
62
SPF Only
74
SPF + DKIM
83
DMARC (p=none)
87
DMARC (p=reject)
94

Why Email is Harder Than You Think

The Reputation System

Every IP address and domain that sends email has a reputation score maintained by major mailbox providers (Gmail, Outlook, Yahoo). This score determines your delivery fate:

ReputationInbox RateWhat Happens
High (90+)95-99%Emails go to inbox
Medium (70-89)60-80%Some emails land in spam
Low (50-69)20-50%Most emails go to spam
Very Low (<50)0-10%Emails are silently dropped

Your reputation is affected by:

  • Bounce rate: Sending to invalid addresses damages reputation
  • Spam complaints: Users clicking "Report Spam" is the strongest negative signal
  • Engagement: If recipients open and click your emails, reputation improves
  • Volume consistency: Sudden spikes in send volume trigger spam filters
  • Content quality: Spammy content patterns (ALL CAPS, excessive links) hurt

IP Warming

You cannot just get a new IP address and start sending 100,000 emails. Mailbox providers treat new IPs with extreme suspicion. IP warming is the process of gradually increasing send volume to build reputation:

Week 1:    50 emails/day
Week 2:   100 emails/day
Week 3:   500 emails/day
Week 4: 1,000 emails/day
Week 5: 5,000 emails/day
Week 6: 10,000 emails/day
...continue doubling until target volume

This is not optional. Skip warming and your first batch of emails will be flagged as spam, poisoning the IP's reputation from day one.

Warming can be automated with a volume scheduler:

interface WarmingSchedule {
  ipAddress: string;
  startDate: Date;
  currentDay: number;
  dailyLimit: number;
  sentToday: number;
  status: "warming" | "warm" | "paused";
}
 
function calculateDailyLimit(warmingDay: number): number {
  // Exponential ramp with daily cap
  const baseLimit = 50;
  const growthFactor = 1.5;
  const maxDaily = 100_000;
 
  return Math.min(
    Math.floor(baseLimit * Math.pow(growthFactor, warmingDay)),
    maxDaily
  );
}

During warming, excess volume is routed to already-warm IPs. The warming IP only receives its daily allocation, carefully distributed across the day to avoid burst patterns.

Shared vs. Dedicated IPs

Most email API providers put small senders on shared IPs. Your deliverability is at the mercy of your neighbors. If another tenant on the same IP sends spam, your reputation suffers.

The shared IP problem:

Shared IP 192.168.1.1
  ├── Your App (legitimate transactional email)
  ├── Sketchy Newsletter Service (high complaint rate)
  └── New Startup (no warming, blasting cold emails)

Result: IP reputation tanks. Everyone suffers.

Dedicated IPs solve this but require enough volume (typically 10,000+ emails/day) to maintain consistent sending patterns. Below that volume, mailbox providers do not have enough data to build a reputation profile.

An IP pool architecture addresses this:

interface IPPool {
  id: string;
  type: "shared" | "dedicated";
  addresses: string[];
  warmingStatus: WarmingSchedule[];
  reputation: number;
  dailyCapacity: number;
  assignedOrganizations: string[];
}
 
function selectIP(pool: IPPool, email: OutboundEmail): string {
  // Route to the IP with the best reputation that has capacity
  const available = pool.addresses
    .map(ip => ({
      ip,
      reputation: getReputation(ip),
      capacity: getRemainingCapacity(ip),
    }))
    .filter(ip => ip.capacity > 0)
    .sort((a, b) => b.reputation - a.reputation);
 
  return available[0].ip;
}

The Email Pipeline Architecture

A robust email sending pipeline has seven stages, each designed to protect deliverability:

Email Request
     |
     v
1. Validation ──── Address syntax, domain MX check,
     |              suppression list check
     v
2. Content ─────── DKIM signing, header construction,
     |              MIME encoding, link tracking injection
     v
3. Rate Control ── Per-domain throttling, IP warming
     |              limits, burst prevention
     v
4. Routing ─────── IP selection, provider selection,
     |              failover assignment
     v
5. Delivery ────── SMTP transmission, TLS negotiation,
     |              retry on soft bounce
     v
6. Feedback ────── Bounce processing, complaint handling,
     |              delivery status updates
     v
7. Analytics ───── Open/click tracking, engagement scoring,
                    deliverability reporting

Stage 1: Validation

Before an email enters the pipeline, it should be validated:

interface ValidationResult {
  valid: boolean;
  checks: {
    syntaxValid: boolean;      // Email address format
    domainExists: boolean;     // MX records exist
    notSuppressed: boolean;    // Not on suppression list
    notBounced: boolean;       // Not a previously bounced address
    notComplained: boolean;    // Not a previous spam reporter
  };
  reason?: string;
}

The suppression list is critical. If an address has bounced or filed a spam complaint, we never send to it again. Repeatedly sending to bounced addresses is the fastest way to destroy IP reputation.

Stage 3: Rate Control

Different mailbox providers have different rate limits and preferences:

// Example values — check provider documentation for current limits
const providerLimits: Record<string, ProviderThrottle> = {
  "gmail.com": {
    maxPerHour: 500,         // Per sending IP
    maxPerMinute: 20,
    burstLimit: 5,           // Max simultaneous connections
    preferredInterval: 3000, // ms between emails
  },
  "outlook.com": {
    maxPerHour: 1000,
    maxPerMinute: 50,
    burstLimit: 10,
    preferredInterval: 1200,
  },
  "yahoo.com": {
    maxPerHour: 300,
    maxPerMinute: 10,
    burstLimit: 3,
    preferredInterval: 6000,
  },
};

Exceeding these limits results in temporary blocks (421 responses) that count against your reputation. We use per-domain rate limiting to stay within each provider's preferences.

Stage 6: Feedback Loops

When a recipient marks your email as spam, the mailbox provider sends a feedback report via the Abuse Reporting Format (ARF). Processing these is non-negotiable:

async function processFeedbackReport(report: ARFReport): Promise<void> {
  // 1. Add to suppression list immediately
  await addToSuppressionList(report.originalRecipient, "complaint");
 
  // 2. Update sender reputation metrics
  await incrementComplaintCount(report.sendingDomain);
 
  // 3. If complaint rate exceeds threshold, alert
  const rate = await getComplaintRate(report.sendingDomain, "24h");
  if (rate > 0.001) {  // 0.1% complaint rate is the danger zone
    await alertOps(`Complaint rate ${rate} exceeds threshold`);
  }
 
  // 4. Log for investigation
  await logComplaint(report);
}

A complaint rate above 0.1% is a red flag. Above 0.3% and you are heading for a blacklist.

Bounce Handling

Bounces come in two flavors:

Hard bounces (550): The address does not exist. Remove it from your list immediately and never send again.

Soft bounces (421, 450): Temporary failures. The mailbox is full, the server is busy, or you are being rate limited. Retry with exponential backoff:

interface BounceRetryStrategy {
  maxRetries: number;
  initialDelay: number;      // ms
  backoffMultiplier: number;
  maxDelay: number;          // ms
}
 
const softBounceRetry: BounceRetryStrategy = {
  maxRetries: 5,
  initialDelay: 60_000,       // 1 minute
  backoffMultiplier: 4,
  maxDelay: 3_600_000,        // 1 hour
};
 
function getRetryDelay(attempt: number, strategy: BounceRetryStrategy): number {
  const delay = strategy.initialDelay * Math.pow(strategy.backoffMultiplier, attempt);
  return Math.min(delay, strategy.maxDelay);
}

After exhausting retries, a soft bounce is promoted to a hard bounce and the address is suppressed.

Authentication: The Non-Negotiable Trio

SPF (Sender Policy Framework)

Declares which IP addresses are authorized to send email for your domain:

v=spf1 include:_spf.transactional.so ~all

DKIM (DomainKeys Identified Mail)

Cryptographically signs each email to prove it was not tampered with in transit. Best practice is to sign every outbound email with a 2048-bit RSA key:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  d=example.com; s=tx1; h=from:to:subject:date;
  b=<base64_signature>

DMARC (Domain-based Message Authentication, Reporting & Conformance)

Tells mailbox providers what to do with emails that fail SPF or DKIM:

v=DMARC1; p=quarantine; rua=mailto:dmarc@transactional.so; pct=100

Without all three, your deliverability ceiling is around 70%. With all three properly configured, you start at 90%+ and build from there.

What Goes Wrong at Scale

Every scaling milestone brings new deliverability challenges:

1,000 emails/day: Shared IP variability. You are at the mercy of your IP neighbors.

10,000 emails/day: Rate limiting starts. Gmail, Yahoo, and Outlook begin enforcing per-IP limits. You need multiple IPs and intelligent routing.

100,000 emails/day: Reputation becomes fragile. A single bad batch (sending to a purchased list, a spike in complaints) can take weeks to recover from.

1,000,000+ emails/day: You are now large enough that mailbox providers assign you a dedicated reputation profile. This is good (your reputation is yours alone) but also means there is no hiding behind a shared IP's aggregate reputation.

The Metrics That Matter

Five deliverability metrics matter most in real-time monitoring:

MetricTargetDanger Zone
Delivery rate>98%<95%
Bounce rate<2%>5%
Complaint rate<0.05%>0.1%
Inbox placement>90%<70%
Time to inbox<30s>5min

Inbox placement is the hardest to measure. Seed testing -- sending test emails to monitoring accounts at major providers and checking whether they land in inbox or spam.

Key Takeaway

Email deliverability is not a feature. It is infrastructure. It requires IP warming, reputation management, feedback loop processing, authentication, rate limiting, and continuous monitoring. Skip any of these and your emails will silently disappear into spam folders.

The developers who treat email as "just an API call" are the ones whose users never receive their password reset emails. Do not be that developer.

See how we handle email infrastructure at Transactional Email.

Written by

Transactional Team

Share
Tags:
email
deliverability
infrastructure

YOUR AGENTS DESERVE
REAL INFRASTRUCTURE.

START BUILDING AGENTS THAT DO REAL WORK.

Deploy Your First Agent