What is email bounce rate, and how do you measure it in Metabase?
Email bounce rate is the share of sent emails that couldn't be delivered. It's the health metric for an outbound motion — a rising bounce rate signals bad data and threatens the sender reputation that keeps the rest of your email landing. Measure it in Metabase from engagement data synced into a database (Outreach, Salesloft, Apollo, Mixmax, and others).
How is bounce rate defined?
The formula is simple: bounced ÷ sent, over a fixed window. What matters is what you count as sent and how you classify a bounce:
- Sent — messages that left your system. Don't include drafts or skipped steps.
- Bounced — messages returned as undeliverable, split into hard and soft.
Hard vs. soft bounces
- Hard bounces — permanent failures (address doesn't exist, domain invalid). These are the real problem: they signal bad list data and damage sender reputation. Keep hard bounce rate low (commonly under ~2%).
- Soft bounces — temporary failures (mailbox full, server down). Usually retried automatically; a persistent soft bounce should be treated like a hard one.
Report the two separately. A blended bounce rate can look fine while a spike in hard bounces quietly wrecks deliverability.
What data does bounce rate need?
- A messages/activity table with a
sent_attimestamp and delivery status. - A bounce type (hard/soft) where the tool provides it.
- The recipient domain, to catch domain-level deliverability issues.
- Segmentation columns: sender, sequence, and list source.
SQL patterns
SELECT
date_trunc('month', m.sent_at) AS month,
COUNT(*) AS sent,
COUNT(*) FILTER (WHERE m.status = 'bounced') AS bounced,
ROUND(
100.0 * COUNT(*) FILTER (WHERE m.status = 'bounced')
/ NULLIF(COUNT(*), 0),
2
) AS bounce_rate_pct
FROM modeled_messages m
WHERE m.sent_at >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY 1
ORDER BY 1;SELECT
u.name AS sender,
COUNT(*) AS sent,
COUNT(*) FILTER (WHERE m.bounce_type = 'hard') AS hard_bounces,
COUNT(*) FILTER (WHERE m.bounce_type = 'soft') AS soft_bounces,
ROUND(
100.0 * COUNT(*) FILTER (WHERE m.bounce_type = 'hard')
/ NULLIF(COUNT(*), 0),
2
) AS hard_bounce_rate_pct
FROM modeled_messages m
JOIN modeled_users u ON u.id = m.sender_id
WHERE m.sent_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY u.name
ORDER BY hard_bounce_rate_pct DESC;Pitfalls
Where this metric applies
- Outreach + Metabase — mailing status and bounce type
- Salesloft + Metabase — email activity status by cadence
- Apollo + Metabase — email events and bounces
- Mixmax + Metabase — message delivery status