Checking an address from your own code, without breaking the signup
You're building the registration flow and somebody has asked for email validation. The library takes ten minutes. The decisions around it are what determine whether this helps or quietly costs you users.
The pressure is unusual for an API call: it reaches out to a stranger's mail server, so its latency is set by infrastructure neither you nor your vendor controls. Any design treating it as a fast local call will break.
The order the work happens in
Do the free checks in your own code first
Shape, a typo suggestion, and an MX lookup on the domain. Those catch a large share of real errors, cost no credits, and return in milliseconds.
Call the API outside the request path
Accept the registration, then verify in a background job or a webhook. The person is never waiting on somebody else's SMTP server, which is the failure this design exists to avoid.
Set a timeout and decide what it means
Two seconds is generous for a check you aren't blocking on. When it expires, treat the result as unresolved rather than as invalid, because a timeout describes your network rather than the address.
Store the result and the date, in separate columns
One column for the verdict, one for when it was taken. Verification is evidence with a shelf life, and a boolean with no timestamp is worthless in six months.
Handle rate limits and retries properly
Back off exponentially on a 429 and make the job idempotent, so a retried request cannot charge you twice or write a second row.
What each result means here
The same four results and their flags, read against this job. A catch-all worth keeping in one situation is one to exclude in another.
| Result | What to do with it |
|---|---|
| Valid | Store it with the date. No user-facing effect. |
| Invalid | Prompt for a correction on next login or by a side channel. Never delete the account. |
| Catch-all | Store as unconfirmed. Business users land here routinely and they are usually your best accounts. |
| Unknown | Store as unresolved with the reason, and re-check on a schedule. It is a statement about the server. |
| Role flag | Store the flag. For a B2B product this is fine; for a per-person account it is worth a question. |
| Disposable flag | The only result worth blocking on, and only if a throwaway signup costs you money. |
How you know it is finished
A registration completes in the same time it did before the integration existed, every account carries a verdict and a date, and no branch in your code turns an unresolved result into a rejection.
What this does not fix
Signup volume is low against list cleaning, so most products live inside the 100 free credits a month plus a $5 top-up for 1,000. Unknown results are not billed, which matters here because a real-time check produces more of them than a batch does.
Questions people ask
Should the API call block my signup form?
No. Run it in the background and fail open. Blocking a registration on somebody else's mail server policy converts their configuration into your lost customer.
What should the code do with an unknown result?
Accept the account, record the reason, and re-check later. An unknown means a server refused to answer, which is a fact about that server rather than about the person signing up.
How long should a verification result be trusted?
Store the date and decide per use. For a transactional address a few months is reasonable. Before you make a large marketing send to the same records, check again.
Try it on the file in front of you
100 free checks a month, no card. Addresses we could not get an answer on come back labeled as unknown, and those are not billed.