Olympus Docs
TroubleshootingInfrastructure issues

High email bounce rate

Verification / recovery emails are bouncing

You're seeing > 5% of emails bounce. This is a deliverability problem.

Categorize bounces

Hard bounces

Email address doesn't exist or domain doesn't resolve. Permanent. Causes:

  • Typo at signup (@gmial.com).
  • User left company (still using old corporate email).
  • Throwaway / disposable address service shut down.

Soft bounces

Temporary failures: inbox full, server unavailable, etc. Usually resolve themselves.

Spam-flagged

Your email landed in spam (technically delivered, but bounced from view). Different metric: open rate.

Diagnose

Pull bounce events from your ESP:

-- Postmark / SendGrid / Mailgun typically have a bounce webhook
SELECT 
  bounce_type,
  COUNT(*) as count,
  array_agg(DISTINCT email_domain) as domains
FROM email_events
WHERE event_type = 'bounce'
  AND created_at > NOW() - INTERVAL '7 days'
GROUP BY bounce_type
ORDER BY count DESC;

Top domains tell you a lot:

  • All @yopmail.com, @mailinator.com, etc. → users registering with disposable. Maybe block.
  • Single corporate domain → DNS or DKIM issue on that domain.
  • Mixed → general deliverability problem.

Fix: Sender reputation

SPF, DKIM, DMARC

These DNS records prove you're authorized to send from your domain. Without them, mail servers reject or spam-folder you.

Check:

dig TXT your-domain.com | grep -i "spf\|dmarc"
dig TXT default._domainkey.your-domain.com  # if DKIM selector is "default"

Should see:

  • v=spf1 include:_spf.your-esp.com -all
  • v=DKIM1; k=rsa; p=...
  • v=DMARC1; p=quarantine; rua=mailto:dmarc@your-domain.com

If any missing, your ESP's docs explain how to add. Wait 24h for DNS propagation.

From address

Use a real address on YOUR domain, NOT a free-mail (e.g., noreply@your-domain.com not your-app@gmail.com). Free-mail "from" addresses go straight to spam.

Reverse DNS

host <your-sending-IP>

Should resolve to a name in your domain. ESPs handle this for you, if you self-host SMTP, configure rDNS.

Fix: Content

Avoid:

  • ALL CAPS subjects
  • Excessive emoji
  • [URGENT] or similar
  • Lots of links
  • Image-heavy emails with little text

Add a plain-text alternative to every HTML email.

Fix: Bounce list

Stop sending to addresses that bounced. ESPs usually do this automatically (suppression list). If you're rolling your own:

-- Mark bounced
UPDATE identities
SET email_status = 'bounced'
WHERE traits->>'email' IN (
  SELECT email FROM email_events WHERE bounce_type = 'hard'
);

-- In Kratos courier, before sending, check this:
-- (via pre-courier webhook, or filter at send time)

Fix: Engagement

Mailbox providers (Gmail, Outlook) downgrade senders whose recipients don't open. Audit:

  • Are you sending too many emails? (Notification preferences, frequency caps)
  • Are your subject lines clear?
  • Are recipients engaging with the link?

Low engagement → reputation drops → bouncing increases over time.

Verification-time email check

To reduce typo-driven bounces, validate at registration:

import { validate as isEmail } from "email-validator";

if (!isEmail(traits.email)) {
  return Response.json({ reject: true, error: "invalid_email" });
}

For deeper check, use a real-time email-validation API (Kickbox, ZeroBounce, Hunter):

const result = await kickbox.verify(traits.email);
if (result.result === "undeliverable") {
  return Response.json({ reject: true, error: "undeliverable_email" });
}

Cost: USD 0.005/check. Worth it for paid signups; debatable for free tier.

Monitor

Dashboard for:

  • Bounce rate (target: < 2%).
  • Complaint rate (target: < 0.1%).
  • Open rate of transactional (target: > 80%, these are expected emails).

On this page