Cold Email at Scale: Prospecting Tech and Deliverability Infrastructure
How I build systems to find leads and land cold emails in the inbox at 20,000+ leads a month. Trigger scripts, mailbox setup, rotation, and deliverability.

I have sent a lot of cold emails over the years. Early on it was for job applications. Now it is for clients.
At some point the work stopped being about the email copy and started being about the systems around it. Who goes on the list. Why they are on the list today. Whether the email actually lands in the inbox. That is most of what I do now.
This post is about two things: finding the right people to email, and making sure those emails land in the inbox. When I say scale, I mean something like 20,000+ leads a month. I am not going to talk much about what to write. Apollo’s cold email guide covers that better than I could.
Most of my week goes into the systems around the emails, not the emails themselves. Scripts to find and score leads. Code hooked into Instantly to watch campaigns and rotate mailboxes. A dashboard so I am not digging through CSV files to check if something is broken.
None of it is fun work. But it is what makes volume possible. I wrote about that pattern in why I love being an individual contributor.
One note before we get into it. The tools and setup I describe here are real. When I mention specific triggers, lead groups, or customer types, those are just examples to show how the system works. Not my actual campaigns.
The part nobody writes about
Most cold email content is about what to say. That makes sense when you are emailing ten people.
It stops making sense at volume. You can write a great email and still get zero replies because it went to spam. You can have good copy and still waste sends because the list is three months old.
So I think about two problems first:
Who should get an email today, and why?
How do you land in the inbox and not spam or promotions?
The copy comes after that.
Finding leads at scale
You have probably read prospecting guides before. Know your customer. Understand their problem. Reach out at the right time. All true.
The hard part at scale is not finding people. It is picking who actually deserves an email this week. Old lists go bad fast.
Clay and the trigger system
I use Clay to build lists and add more data to leads. Clay answers “who should I reach out to?” pretty well. Company info, contacts, filters for your ideal customer, lookalikes.
It does not answer “why am I reaching out to them right now?”
That is what my trigger system is for. I have a Python script that watches for events in the market and alerts me when something worth acting on happens. In a made-up example, that might be a funding round, a new hire, a hiring spike, or a rule change. Yours will depend on who you sell to. The point is simple: there is a real reason to email today, not just a name on a list.
The flow:
- Market events · triggers fire
- Parallel · search
- Claude SDK · cleanup
- Enrichment API · scoring
- Ranked list · prioritized leads
- Clay · enrichment
- Instantly · campaign
Parallel searches across news, filings, job posts, and public data. The results are messy. A pass through the Claude SDK cleans them up, fixes company names, removes duplicates, and pulls out the fields I need.
Then everything goes through a custom API that scores how good the lead is, how strong the signal is, and how recent it is. Not every event is worth an email. This step filters out the noise and ranks what is left.
Good leads go into Clay for the last step: contacts, company details, whatever the campaign needs. From there it goes into Instantly, usually split by trigger type so each group gets its own campaign.
I am not blasting a stale spreadsheet. Something changed at the company, the script caught it, and the lead showed up ready to send.
What I need before a lead goes out
Three things on every lead:
- Good fit for who I am trying to reach
- The trigger (what changed, and when)
- A priority score
If you are still doing that by hand past a few hundred leads a week, it will break.
Split lists by signal
I do not run one giant list. I run small groups based on what happened. As an example: say you sell to mid-size SaaS companies. Everyone who just raised money goes in one campaign. Everyone with a new VP hire goes in another. Each gets its own campaign and send limit in Instantly.
Everyone in the group shares the same signal, so the email does not need fake LinkedIn personalization on every row. The finding-leads system already did the work.
Making sure emails land in the inbox
This is the part I actually enjoy as an engineer. Most teams ignore it until their domains start getting blocked.
Your setup has one job: land in the inbox. Not spam. Not promotions. Not nowhere.
What I run
- Primeforge and Instantly for mailboxes
- Instantly for sending, warmup, and campaigns
- NeverBounce or ZeroBounce to check emails are real before sending
- Python on top of Instantly’s APIs to manage mailboxes, track stats, read replies, and handle day-to-day ops
- A small web dashboard I built to see everything in one place
Hundreds of mailboxes. Warmup schedules. Campaign setup. Pulling bad mailboxes when things start slipping. Most of it runs through scripts and the dashboard instead of clicking around in Instantly all day.
The basics
Multiple providers
I spread mailboxes across Instantly and Primeforge so everything is not tied to one place.
Warmup
Two to three weeks before real sends. Instantly has warmup built in. Do not start blasting from a brand new inbox.
Send limits
Around 20 emails per day per mailbox. 100 active mailboxes is roughly 2,000 per day. Add more mailboxes to scale. Do not push one inbox harder.
Check emails before sending
Bad addresses hurt your sender reputation fast. Run the list through NeverBounce or ZeroBounce before a campaign goes live.
Match mailbox to recipient
Outlook mailboxes for Outlook users, Gmail for Gmail users. Sounds small. It matters.
Rotation
Spread sends across mailboxes so one inbox is not doing all the work. Instantly handles most of this if you set campaigns up right.
Mailbox pools
Split mailboxes into three groups instead of using everything at once:
- 60% for live campaigns
- 30% for testing new copy or new lead groups
- 10% kept aside, warmed and ready to swap in when something burns
Domains die. Having spare mailboxes ready is cheaper than panicking after a campaign tanks.
Python and the dashboard
Checking inboxes by hand stops working past a few dozen mailboxes. Instantly’s UI is fine for setup. It is not fine for running things day to day at volume.
So most of the work runs through Python on Instantly’s APIs. Which mailboxes go to which campaign. Pulling stats. Reading replies. Watching bounces. Rotating mailboxes when something slips. The scripts handle the boring stuff.
On top of that I built a small web dashboard. One screen for campaign stats, bounce rates, mailbox health, and whether leads are getting followed up on.
It is not fully automated. The scripts and dashboard make the work faster, but I still make the calls. What they do well:
- Watch bounce rates on campaigns. Instantly flags these automatically, but I monitor them myself so I can act before Instantly warns me
- Surface mailboxes with bad bounce or reply trends
- Pull replies so I can read what is actually working
The code watches and alerts. I decide when to swap mailboxes, pause a campaign, or change copy. The dashboard just puts it all in one place so I am not guessing.
5.7.1 bounces
This was the problem that ate the most time once volume got serious.
5.7.1 bounces are not the usual “this email does not exist” bounce. The receiving server basically does not trust you right now. You can do everything right and still hit this.
What helped:
Watch bounces per campaign through the API. Once you cross a limit, swap email versions.
Spintax for real variation. Small word swaps so spam filters do not learn one exact email.
{{RANDOM | Hey | Hi | Hello}} {{firstName}},
Add a few more swaps in the subject and body and you get many different versions of the same email.
Test inbox placement before sending at scale. Gmail, Outlook, corporate filters. Spintax plus rotation got us to around 99% inbox placement in testing.
Turn off open tracking. The tracking pixel hurts deliverability. I watch reply rates instead.
Do not skip these
Warmup before scale. Check emails before sending. Bounce alerts before things get worse. Swap versions when something slips. Match mailbox type to recipient. Use code to monitor, not manual inbox checks.
Stuff I see teams get wrong
Copy gets all the attention. Inbox placement gets ignored until a domain is dead.
Stale lists. Things change. Your lead-finding system needs to stay fresh or you are emailing people who are no longer a fit.
One mailbox pushed too hard. That is not scale. That is gambling with your reputation.
Open tracking. Noisy, often wrong, and bad for inbox placement.
Buying a list and blasting it. That is not prospecting.
Manual work past 500 leads a week. You will not hold volume if you are checking mailboxes and bounce reports by hand.
If you are starting from zero
Pick one customer type and one trigger. Not 20,000 leads. One profile, one reason to reach out now.
Get the lead-finding system working end to end for that one trigger before you worry about volume.
Set up your mailboxes early. A few domains, warmup for a few weeks, check the list, test inbox placement. Ten emails from a burned domain teach you nothing.
Set up monitoring from day one. Bounce alerts, rotation tracking, reporting. Do not wait until a domain gets flagged.
Add new lead groups before you push existing ones harder.
None of the ops work is fun. Warmup, checking lists, bounce monitoring, mailbox rotation. But it is what makes the whole thing work at volume. I would rather spend a week on setup than rewrite email copy for the hundredth time.