Skip to main content

Proxy 25

EMAIL INFRASTRUCTURE · SCALABILITY · ARCHITECTURE · 2026

How to Bypass Email Infrastructure
Scalability Bottlenecks

Kiran's verification pipeline never threw an error when volume tripled overnight. It just got slower — forty-seven minutes per job, then a backlog of two hundred and eighty thousand. Four architectural constraints were hiding behind each other, and none of them showed up as a failure.

The pipeline that broke without breaking

Kiran had spent four months writing the verification pipeline at his company. Not configuring a SaaS tool. Not stitching together third-party APIs. Actually writing it — a custom pipeline designed around the specific way his business processed contact data, integrated with their CRM, their enrichment layer, and their outbound sequencing tool.

At ten thousand verifications per day, the pipeline ran exactly as intended. Jobs completed in under ninety seconds. Error rates stayed under one percent. His team relied on it the way you rely on something that has never given you a reason to question it.

Then his company closed a partnership that tripled the volume of contacts coming in overnight. Thirty thousand verifications per day, starting Monday.

The pipeline did not throw an error. It did not crash. It accepted every job, put every job in the queue, and processed every job in the order it received it. Nothing was wrong in any way the system knew how to report.

90s → 47m
Job completion time, week of the volume spike
280,000
Jobs in the backlog by Wednesday
4
Layered architectural constraints found

He reached the Proxy25 line through a mutual contact who told him that the team there had seen the inside of more verification pipelines than anyone else they knew, and that when a pipeline problem did not make obvious sense, that was the kind of call worth making.

That was accurate. What I found across two days of working through Kiran's codebase and logs was not a single broken thing. It was four architectural constraints, each one sitting behind the performance of the previous, each one only becoming fully visible as the one in front of it was addressed.

Why email infrastructure scalability failures look like slowness, not failure

The reason Kiran's team spent a week trying to diagnose the problem before calling anyone was that the problem produced no error signal. Every metric that reports failure was nominal. The pipeline was succeeding at processing jobs. It was just succeeding slowly enough that the practical effect was indistinguishable from failure.

A web application approaching a performance ceiling typically signals it — response times rise, error rates climb, the dashboard shows something to act on. Email pipelines operate differently because of two structural properties.

Asynchrony A verification job submitted to a queue does not produce an immediate response the way an API call does. It produces a receipt. The gap between submission and delivery is only visible in the aggregate — when results submitted at 9am are completing at 4pm, and someone asks why.
Constraint masking At any moment, the binding constraint in a multi-stage pipeline is whichever stage processes slowest. Every stage after it looks healthy, because it never receives more input than the slow stage allows through. Clear that constraint, and the next stage immediately faces demand it was never tested at.

Kiran's pipeline had four layers of constraint behind each other. Each one had been masked by the one in front of it. Ten thousand daily verifications put the first constraint under just enough load to pace all the rest. Thirty thousand revealed the first constraint clearly — and then, sequentially, every other.

01Layer one

The write that waited for itself

The first constraint wasn't in the SMTP layer or the proxy layer. It was in the database. Every time a verification job completed, the result was written synchronously before the next job was picked up — clean, predictable, auditable, and completely sensible at ten thousand daily verifications.

At 10,000 verifications per day with each write taking roughly 11ms, the total cost across a full day was negligible. At 30,000 per day, the same pattern pushed the database past its provisioned capacity. At peak hours, individual write latency climbed to 120ms — serialized, one write at a time, before the next job could start.

Hidden cost Sixty minutes of pipeline time per day spent waiting for database commits. Not SMTP. Not network round trips. Writing completed results to a database, one row at a time, each row making the next row wait.

The fix was batching: hold results in an in-memory buffer, flush in batches of five hundred every thirty seconds. The database went from thirty thousand individual transactions to sixty batches an hour. Total pipeline time spent on writes dropped by 92%.

This is the class of constraint that's architecturally invisible at low volume. Eleven milliseconds feels free. Applied serially at scale, it becomes the dominant cost — not because the code changed, but because the cost structure of the same code changed underneath it.

02Layer two

The worker count that was never meant for this load

After the write fix, the queue cleared faster — for about six hours. Then Kiran's team hit the second layer: a fixed worker pool sized at twenty, which had provided comfortable headroom at ten thousand verifications a day.

24,000
Theoretical peak jobs/hr with 20 workers
12,000
Actual throughput once housekeeping overhead is counted
20,000
Peak jobs/hr after distributing to 3 servers

Between jobs, each worker deserializes from the queue, establishes network state, resolves the destination, manages the SMTP connection object, and writes to the result buffer — real time that never shows up in per-job processing figures. Beyond forty workers on a single machine, adding more began reducing per-worker throughput as OS scheduling and socket buffer overhead ate the gains.

The fix was distribution, not concentration: three servers running fourteen workers each, rather than one server running forty. Each worker carries an outbound connection, a DNS resolution, and an active SMTP session — per-worker costs the network stack and OS handle separately, with a capacity limit independent of the application-level worker count.

03Layer three

The DNS time nobody was measuring

After the worker fix, the team projected the 280,000-job backlog would clear in thirteen hours. It took twenty-two. Nine hours, unaccounted for. No error, no degraded output — just a gap between what the throughput numbers predicted and what the clock showed.

The gap was DNS resolution. Kiran's pipeline made a fresh MX record query for every single job — no caching. A batch of four hundred addresses at the same company domain made four hundred identical queries. Under the load of forty-two concurrent workers, resolution times climbed from 60–80ms to 140–180ms at peak.

Hidden cost 80 minutes of pipeline time per day — 4,800 seconds — spent asking the same DNS servers the same questions repeatedly, when the answers hadn't changed.

The fix was MX record caching with TTL-aware expiry. On a real enterprise contact list where many contacts share company domains, cache hit rate ran above 65%. The next comparable backlog cleared in fourteen hours instead of twenty-two.

04Layer four

The queue that treated everything as equally urgent

Three layers cleared. Then one question exposed the fourth: if a salesperson needed a single contact verified before a call in twenty minutes, how long would they wait? The honest answer was nobody knew — it depended entirely on what else was already in the single first-in-first-out queue.

A batch of forty thousand addresses submitted at 9am sat ahead of an urgent single verification submitted at 9:15 for a 9:30 call. At ten thousand daily verifications this ordering rarely mattered. At thirty thousand, with backlog events occurring, the difference between "needs to finish in minutes" and "needs to finish by end of day" was invisible to the queue.

The fix was queue separation: an urgent lane for single-address and small CRM-triggered verifications, and a standard lane for bulk batches. Workers service the urgent lane first, and fall back to the standard lane only when it's empty. Total capacity is unchanged — only the ordering of how it's applied changes.

After separation, a single verification completed in under ninety seconds regardless of what sat in the standard lane. Bulk batches completed in four to six hours — well within what the data team actually needed. Treating all jobs identically in a queue is a design decision, not a neutral default.

The episode that revealed what was still missing

Two weeks into the rebuild, a large enterprise domain changed its mail server configuration so that every SMTP connection attempt stalled at the TCP stage for twenty-eight seconds before timing out. Not rejected — stalled. With workers distributed across three servers, the stalls occupied enough of them that two servers' effective output dropped to near zero for ninety minutes.

The pipeline had no mechanism to notice one destination was failing at an abnormal rate and stop sending it workers. The fix was a circuit breaker: track failure rate per destination domain in a rolling window; when more than 25% of attempts to a domain fail or time out within five minutes, open the circuit and route new jobs for that domain to a deferred queue. Probe every five minutes; close the circuit the moment a probe succeeds.

A circuit breaker doesn't speed up healthy processing. It stops one misbehaving destination from consuming capacity that belongs to everyone else in the queue.

The missing feedback from pipeline to pipeline

Across all five issues, one pattern repeated: the pipeline had been built to process jobs, not to communicate its own state back to the systems submitting them. When any layer was constrained, the CRM integration and batch scheduler kept submitting at their normal rate regardless — a backpressure gap.

The fix was a lightweight queue-state endpoint the CRM integration and batch scheduler check before submitting. Past 150 jobs in the urgent lane, single submissions delay fifteen seconds before retrying. Past 4,000 jobs in the standard lane, new batches hold until depth drops below 2,500. The CRM doesn't need to understand why the pipeline is busy — only the signal to pause and the signal to resume.

What the numbers looked like when the rebuild was done

All six changes — write batching, distributed workers, MX caching, queue separation, circuit breaker, backpressure — went in across three weeks, in the order the constraints were discovered. Order mattered: distributing workers before fixing the write serialization would have spread the bottleneck across three servers instead of removing it; MX caching had to come after worker distribution, because the DNS constraint was masked until the worker constraint was cleared.

3m 50s
Median job completion at 30,000/day, post-rebuild
88 min
Time to clear a stress-test backlog at 55,000/day
65,000
Daily verifications run without hitting a new constraint

None of the six changes required exotic techniques — write batching, horizontal worker distribution, DNS caching, queue separation, and circuit breakers are all standard, well-documented patterns. What wasn't standard was having all six in the right sequence, in a pipeline where the constraints interact in the specific ways they do when email verification is the workload.

Where this connects to the Proxy25 layer

Proxy25 sits at the SMTP infrastructure layer — the proxy the pipeline connects through when making verification queries. Kiran's bottlenecks were all application and architecture layer: writes, workers, DNS, queue logic. Distinct engineering problems from the infrastructure the pipeline connects to.

The connection worth making explicit: the circuit breaker Kiran added to detect misbehaving destination domains is structurally the same approach Proxy25 uses at the infrastructure layer to manage the relationship between verification IPs and receiving mail servers. Track the quality of what each destination is producing. Stop trusting destinations producing poor output. Resume when they recover. That pattern works at the queue level, and it works at the proxy level.

Built for the volume your pipeline is finally running at

Proxy25 provides the proxy infrastructure layer for verification pipelines — IP addresses with years of clean SMTP connection history with major mail servers.

Start with 500 free credits →