Real-Time Email Verification on Signup Forms: A Latency Guide
Run real-time verification in layers with a hard time budget. Syntax runs instantly in the browser. On submit, your server checks typos, disposable domains and MX records in tens of milliseconds, then calls the SMTP check with a timeout of about 3 seconds. Block only definitive failures. On timeout, unknown or catch-all, fail open: accept the signup and re-check later.
The failure people worry about is a slow form. The failure that actually costs money is a form that rejects real customers because a mail server was slow to answer. This post is about designing for both, with timings we measured and the timeout behaviour vendors document.
The latency budget
Each layer has a very different cost, so put the cheap, definitive checks first and give the slow one a hard limit.
| Layer | Where it runs | Typical time | Can it give a definitive "no"? |
|---|---|---|---|
| Syntax | Browser and server | Under a millisecond | Yes, for malformed input |
Typo suggestion (gmial.com) |
Browser or server | Under a millisecond | No. It suggests, the user decides |
| Disposable domain list | Server | Under a millisecond (a set lookup) | Yes, if you choose to reject disposable addresses |
| MX lookup | Server | Tens of milliseconds (measured below) | Yes, for non-existent domains and null MX |
| SMTP mailbox check | Verification API | Hundreds of milliseconds to many seconds | Yes, for rejected mailboxes; no for catch-all or timeout |
What we measured for DNS
We timed 36 MX lookups with dig on 1 October 2026, from a residential connection, against two public resolvers (1.1.1.1 and 8.8.8.8), three runs each for six domains including two that do not exist. The raw data is in our research notes.
| Measure | Result |
|---|---|
| Fastest | 7 ms |
| Median | about 17 ms |
| Slowest | 226 ms |
| Lookups over 100 ms | 6 of 36 |
The pattern was what you would expect from caching: the first query for a domain was sometimes around 100 ms, repeats were usually 10 to 20 ms, and a made-up domain that no resolver had cached produced the slowest result. Your server's resolver and location will differ, so measure your own, but the order of magnitude is the point: the DNS layer costs almost nothing.
Why the SMTP layer needs a hard limit
The SMTP check is slow for reasons you cannot control. The standard that governs it, RFC 5321 section 4.5.3.2, recommends that mail clients wait at least 5 minutes for a server's initial greeting and 5 minutes for a reply to RCPT TO, noting that "Many SMTP servers accept a TCP connection but delay delivery of the 220 message until their system load permits." Those values were designed for delivering mail, not for a person waiting on a form.
Verification APIs handle this with a timeout parameter, and the documented behaviour is consistent:
- ZeroBounce: the validate endpoint accepts a timeout of "3 - 60 seconds"; "If met, the API will return unknown / greylisted." The default is 30 seconds.
- NeverBounce: the single check endpoint takes "The maximum time in seconds we should try to verify the address" and returns
unknownwhen it is reached. Its documentation adds that "The total request time can exceed this timeout, as network latency is not taken into consideration."
That last sentence is why you need your own timeout as well as the vendor's. The vendor's timer covers its work, not the network round trip to and from your server.
How long users will wait
Aim to finish the whole check within about a second, and never leave the user without feedback. Jakob Nielsen's long-standing response-time limits are a useful guide: "0.1 second is about the limit for having the user feel that the system is reacting instantaneously", "1.0 second is about the limit for the user's flow of thought to stay uninterrupted", and "10 seconds is about the limit for keeping the user's attention focused".
A note on Core Web Vitals: Google's Interaction to Next Paint metric treats 200 ms or less as good. INP measures how quickly the page paints after an interaction, not how long a network request takes. If your submit handler immediately shows a "Checking your email…" state and verifies asynchronously, a two-second API call does not hurt INP. If it blocks the main thread or shows nothing until the answer arrives, it can.
A practical budget:
| Stage | Budget |
|---|---|
| Browser: syntax and typo hint, on blur | Instant |
| Server: syntax, disposable, MX | Under 300 ms including the network round trip |
| Server: SMTP check via API | Hard cap around 3 seconds on your side, with the vendor timeout set at or below that |
| Anything beyond the cap | Fail open |
The 3-second figure is our recommendation, not a standard. Pick a number between 2 and 5 seconds that suits how much a signup is worth to you, and enforce it.
Fail open, fail closed: the rules
Block on proof, not on doubt. The decision should depend on what the check actually established.
| Outcome | Action at the form | Why |
|---|---|---|
| Malformed syntax | Block, with a clear message | Definitive |
| Domain does not exist (NXDOMAIN) or has a null MX | Block, suggest a correction if it looks like a typo | Definitive. See syntax vs MX vs SMTP |
Mailbox rejected (550 5.1.1 or similar) |
Block, ask the user to check the address | Definitive |
| Disposable domain | Your policy: block for trials, allow for newsletters | Real mailbox, low intent. See blocking disposable emails |
Typo suggestion (gmial.com) |
Do not block. Show "Did you mean gmail.com?" | The user may really be at that domain |
| Valid | Accept | |
| Catch-all / risky | Accept, flag for confirmation | Cannot be confirmed by anyone. See catch-all domains |
| Unknown, timeout, API error | Accept, queue a background re-check | Your verifier's problem, not the user's |
| DNS SERVFAIL | Accept, re-check later | Temporary DNS failure, not a dead domain |
The last three rows are the fail-open cases. A vendor outage, a slow mail server or a greylisting reply should never cost you a customer. Accept the address, mark it unconfirmed, and let the background re-check and your confirmation email settle it.
A minimal server-side flow
This is the shape of it in TypeScript-like pseudocode. verifyMailbox stands for whichever verification API you use; check its documentation for the real request format and result names, which are mapped across vendors in verification results explained.
async function checkSignupEmail(email: string): Promise<Decision> {
if (!isWellFormed(email)) return block("That email address isn't valid.");
const domain = email.split("@")[1].toLowerCase();
const suggestion = suggestTypoFix(domain);
const mx = await lookupMx(domain); // tens of ms
if (mx.kind === "nxdomain" || mx.kind === "null-mx") {
return block("We can't deliver to that domain.", suggestion);
}
if (mx.kind === "temporary-failure") return acceptAndRecheck(email);
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 3000);
try {
const result = await verifyMailbox(email, { signal: controller.signal });
if (result === "invalid") return block("That mailbox doesn't exist.", suggestion);
if (result === "valid") return accept();
return acceptAndRecheck(email); // risky, catch-all, unknown
} catch {
return acceptAndRecheck(email); // timeout or API error: fail open
} finally {
clearTimeout(timer);
}
}
Three details in that code matter more than they look. The MX lookup's temporary failure path accepts rather than blocks. The catch accepts, so an outage at your vendor is invisible to users. And every block returns a message the user can act on, because "invalid email" with no hint sends people away rather than fixing the typo.
Security and abuse
Keep the API key on the server and treat your verification endpoint as something attackers will find.
- Never call the verification API from the browser. Anyone can read a key in front-end code and run verifications on your account.
- Rate-limit your endpoint per IP and per session. A form that tells anyone whether a mailbox exists is a free verification service for whoever scripts it.
- Keep messages vague enough on public forms. "We can't deliver to that address" helps a real user; it need not reveal more than the user typed.
- Pair it with bot protection. Verification does not stop a bot using real addresses. See stopping fake signups.
Throughput and cost
Check your vendor's rate limits against your peak signup rate, not your average. SimpleVerifier verifies up to 45 addresses per minute per account. That is ample for most signup forms, but a site that takes bursts of hundreds of signups a minute would hit it, and the fail-open design above is what keeps those users from noticing. Per-check pricing at other vendors makes the same point from the other side: verify on submit, not on every keystroke. The verification cost calculator compares per-address costs if you are pricing it.
Real-time verification is not consent
Verification proves a mailbox exists. It does not prove the person filling in your form owns it or wants your email. For that you still need a confirmation step; see double opt-in vs email verification.
Practical takeaway
Put syntax in the browser, put the cheap DNS checks on the server first, give the SMTP check a hard cap of a few seconds that includes network time, and block only on definitive answers. Everything inconclusive gets accepted, flagged and re-checked in the background. To see how a given address resolves before you wire anything up, try it in the free single email checker.
Common questions
How long does real-time email verification take?
The DNS part is fast: in our own measurement, MX lookups took a median of about 17 milliseconds. The SMTP mailbox check depends on the recipient's server and can take seconds, which is why verification APIs let you set a timeout and return unknown when it is reached.
Should a signup form block users when email verification fails?
Only when the answer is definitive: broken syntax, a domain that does not exist or accepts no mail, or a mailbox the server rejected. If the check times out or returns unknown or catch-all, let the user through and re-check in the background. Blocking on an inconclusive result turns your verifier's limits into lost signups.
Should I call the verification API from the browser?
No. Call it from your server. A key in front-end code can be copied and used to run verifications on your account, and a public endpoint that reports whether a mailbox exists can be abused to check addresses in bulk. Rate-limit your own endpoint as well.
Does real-time verification replace double opt-in?
No. Verification tells you a mailbox exists; double opt-in tells you the person who typed the address controls it and wants your mail. Use verification to catch typos and dead addresses at the form, and confirmation emails to prove consent.
Verify unlimited addresses for $29.99/month
Real SMTP mailbox checks. No credits, no per-email fees.
Get Started