Verification as a step in the pipeline
Data teams meet this as a pipeline step rather than a product. Something upstream produces addresses, something downstream sends to them, and verification sits in between as a job with a schedule and a cost.
The design questions are the usual ones: what to store, how to avoid redundant work, and how to make the result useful to people who will never read this documentation.
A verdict without a timestamp becomes a lie
Store a verdict in a column called email_status and in eighteen months it will be quoted in a dashboard as current. Addresses decay at roughly a quarter a year in B2B, so a two-year-old valid is close to meaningless.
Store the verdict, the check date and the coverage of the run that produced it. Then a downstream consumer can apply its own staleness rule, and the segmentation query that filters on it is honest about what it is filtering.
The second design question is what to do with unknown. It is not a verdict, it is an absence of one, so modeling it as a third state rather than folding it into invalid keeps the re-check queue obvious and prevents a slow mail server from silently deleting real customers.
How the work gets done
The order that matters for data teams, rather than a generic checklist.
Check only what has changed or aged
New addresses since the last run, plus anything whose verdict is older than your staleness threshold. Re-verifying a stable table every night is spending credits to confirm last night's answer.
Store three columns, not one
Verdict, checked_at and the batch's coverage. The first without the second is a claim that quietly expires; the third tells you how much of that run got an answer at all.
Model unknown as its own state
Not a flavor of invalid. It drives a re-check queue, it costs nothing, and folding it into invalid deletes real customers on the basis of a mail server having a slow afternoon.
Use idempotency keys on submission
A retried job must not create a second batch. Key on the run id and a lost response becomes a replay rather than a double charge.
What verification will not do here
What it costs
At the 500,000 tier a full pass is $549, or $0.0011 an address. Because unknowns and duplicates are never billed, an incremental job's real cost is usually well below the row count it processes.
Every tier works the same way. Unknown results and duplicates are never billed, and credits do not expire.
Questions we get asked
How often should a warehouse table be re-verified?
Quarterly for B2B, where job changes drive most of the decay. Measure your own rate once by re-checking a cohort and comparing, and use that instead of a rule of thumb.
Should unknown results be retried immediately?
No. Unknown usually means greylisting or throttling, which resolve over days rather than minutes. Re-check in two weeks and expect a fair share to convert.
Can I get results streamed as the batch runs?
Yes. The results endpoint pages on a cursor rather than an offset, which is what makes reading a batch that is still being written safe.
Try it on your own list first
100 free checks a month, no card. Run a sample and read the unresolved count before you decide anything.