Developer resources

Handling rate limits in email verification APIs: a practical guide

Every email verification API rate-limits you eventually. Here are the patterns that handle it gracefully without failed verifications.

AD

Admin

June 25, 2026 · 3 min read

Every email verification API rate-limits eventually. Free tiers have low limits, paid tiers have higher limits, enterprise tiers have flexible limits, but no tier is unlimited. The right way to handle rate limits is not "throw a louder error" but a layered design: caching, queuing, exponential backoff, and graceful degradation. Here is the production pattern.

The rate limit response

When you exceed the limit, the API returns HTTP 429 Too Many Requests. The response usually includes headers:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1700000000

The Retry-After header tells you how many seconds to wait. The X-RateLimit-Reset header tells you the epoch timestamp when the window resets.

Pattern 1: exponential backoff

The simplest retry strategy. On 429, wait, retry, wait longer if it fails again.

async function verifyWithRetry(email, attempt = 0) {
    const res = await fetch('https://mailoclean.com/api/v1/verify', { ... });

    if (res.status === 429 && attempt < 5) {
        const retryAfter = parseInt(res.headers.get('Retry-After') || '1', 10);
        const delay = retryAfter * 1000 * Math.pow(2, attempt);
        await sleep(delay);
        return verifyWithRetry(email, attempt + 1);
    }

    return res.json();
}

Works for low-volume sporadic checks. Breaks at high volume.

Pattern 2: token bucket on the client

Track your own rate limit locally. Never exceed it. The simplest implementation:

class RateLimiter {
    constructor(maxPerMinute) {
        this.maxPerMinute = maxPerMinute;
        this.tokens = maxPerMinute;
        setInterval(() => { this.tokens = this.maxPerMinute; }, 60000);
    }
    async take() {
        while (this.tokens <= 0) await sleep(100);
        this.tokens--;
    }
}

const limiter = new RateLimiter(60);
async function verify(email) {
    await limiter.take();
    return fetch('https://mailoclean.com/api/v1/verify', { ... });
}

Predictable, never trips 429.

Pattern 3: queue + background worker

For high-volume jobs, do not verify in the request handler. Push verification onto a queue. A background worker processes the queue at a sustainable rate. The user gets an immediate response; verification happens within seconds.

// Web handler
app.post('/signup', async (req, res) => {
    const user = await createUser(req.body);
    queue.add('verify-email', { userId: user.id, email: user.email });
    res.json({ user, status: 'verification_queued' });
});

// Worker
queue.process('verify-email', async (job) => {
    const result = await verifyEmail(job.data.email);
    await db.users.update(job.data.userId, {
        email_status: result.status,
        email_score: result.score,
    });
    if (['invalid', 'disposable'].includes(result.status)) {
        await sendInternalAlert(job.data.userId);
    }
});

Pattern 4: bulk endpoint instead of single API

If you have many addresses, submit them as a bulk batch instead of calling single-verify in a loop. The bulk endpoint has its own throughput, dramatically higher than the single API. MailoClean bulk API handles up to 1M addresses per batch.

What to do when 429 won't budge

If you are persistently hitting 429:

  1. Add caching. Repeated checks on the same address should hit your local cache, not the API. 24h cache is reasonable.
  2. Move to the bulk endpoint for batch jobs.
  3. Upgrade to a higher rate-limit tier.

Graceful degradation

Sometimes you genuinely cannot verify in time (API is down, you are rate-limited and the queue is backed up). For non-critical paths (signup forms, contact captures) the right default is "accept the input, flag the user as needing verification, reverify in background within the hour".

For critical paths (password reset, account recovery), errors should surface clearly: "Could not verify your email right now. Please try again in a moment."

FAQ

What is MailoClean's rate limit?

60 requests per minute per API key on standard plans. Higher limits available on enterprise.

Does the bulk endpoint share the same rate limit?

No, bulk has its own throughput (effectively unlimited for the batch size; you submit once and poll).

Do retries cost credits?

No. 429 responses do not count against your credit balance. Only successful 200 responses cost a credit.

Build for the limit you have

Pick a pattern, ship it. MailoClean API docs have copy-paste examples for each.

Ready to try MailoClean?

Clean your list and start sending with confidence.

Free verifications included with every account. Credits never expire.

AD

Admin

Email deliverability writer at MailoClean

Back to all posts

Keep reading

Related posts