Limits and pacing
Two separate mechanisms bound how fast verifications happen, and they fail in completely different ways. Confusing them is the usual reason a bulk job looks broken.
The rate limit — a 429, about you
Section titled “The rate limit — a 429, about you”Requests are limited per credential and per source address. The ceilings sit well above what an interactive integration produces; they exist to bound a runaway client rather than to shape normal traffic.
A 429 carries Retry-After. Honour it, and back off exponentially past it.
The same status also answers a request pattern that looks like directory harvesting — many addresses at one domain, in a shape nobody’s signup form produces. If you are legitimately grading a list, that is a different product shape and worth telling us about rather than working around.
The pacing — an unknown, about a destination
Section titled “The pacing — an unknown, about a destination”The other limit is not about you at all. Each destination has a speed and a daily volume this service is willing to send it, and the two are separate: a probe a second is defensible, and 86,400 sessions a day to one provider from an address that never delivers a message is not the same claim.
When a destination’s allowance is spent, the answer is unknown,
immediately. There is no queue and nothing to wait for. The result carries
SMTP_PACING_REFUSED, and — because it is our decision rather than a failure
you caused — it is free.
That has a consequence worth planning around:
Submitting a million addresses at once does not take longer. They come back unanswered and unbilled, at whatever rate your credential allows.
So the useful question for bulk work is not “how deep is the queue” but “what intake rate is worth using”, and the answer depends on the mix of destinations in your list rather than on anything about your account. A list that lands mostly on one large provider is bounded by that provider’s allowance no matter how it is submitted. Ask us before running a large list and we will work the schedule out against the real numbers.
Priority — who yields, never who is granted
Section titled “Priority — who yields, never who is granted”Every credential carries one of three classes:
| Class | Who is waiting |
|---|---|
interactive |
A person with a page open. Yields to nothing. |
transactional |
Your own request, a machine holding the connection open. |
bulk |
A list. And every retry, whatever credential it belongs to. |
Two things about it:
- It never grants anything. Every ceiling that would refuse a probe still refuses it. The class decides only which of two waits when both cannot go now. It is not a service tier and it is not sold.
- It is a property of the credential, not the account. Hold a transactional key for your signup flow and a bulk key for your nightly list, and the second yields to the first — including to your own.
An unstated class behaves as transactional: the middle, never the most urgent.
A list served as transactional costs other callers some allowance for a while; a
signup flow served as bulk is refused exactly when somebody is waiting.
Why we do not just go faster
Section titled “Why we do not just go faster”Remote provider safety outranks our latency goals. When a destination throttles,
we slow down, defer, or answer unknown — we never raise concurrency to keep up
with ingress. A destination that has backed us off is a destination we will
still be able to ask tomorrow.