Building a Bulk Asynchronous Bird Recipient Validation Tool
·
May 26, 2022
Key Takeaways
The author built a bulk recipient validation tool to validate millions of email addresses efficiently using Bird’s Recipient Validation API.
Node.js proved faster and more scalable than Python due to its non-blocking I/O and lack of GIL limitations.
The tool reads CSV files asynchronously, calls the validation API for each email, and writes results to a new CSV in real time.
The approach avoids memory bottlenecks and improves throughput to about 100,000 validations in under a minute.
Future improvements could include better retry handling, a user-friendly UI, or migrating to serverless environments for scalability.
Q&A Highlights
What is the purpose of the Bulk Asynchronous Recipient Validation Tool?
It validates large volumes of email addresses by integrating directly with Bird’s Recipient Validation API, outputting verified results quickly without manual uploads.
Why was Python initially used and later replaced by Node.js?
Python’s Global Interpreter Lock (GIL) limited concurrency, while Node.js allowed true asynchronous execution, resulting in far faster parallel API calls.
How does the tool handle large files without running out of memory?
Instead of loading all data at once, the script processes each CSV line individually—sending the validation request and immediately writing results to a new CSV file.
What problem does the tool solve for developers?
It enables email list validation at scale, overcoming the 20MB limit of SparkPost’s UI-based validator and eliminating the need to upload multiple files manually.
How fast is the final version of the program?
Around 100,000 validations complete in 55 seconds, compared to over a minute using the UI version.
What issues were encountered on Windows systems?
Node.js HTTP client connection pooling caused “ENOBUFS” errors after many concurrent requests, which were fixed by configuring axios connection reuse.
What future enhancements are suggested?
Adding error handling and retries, creating a front-end interface, or implementing the tool as a serverless Azure Function for better scalability and resilience.

For someone who is looking for a simple fast program that takes in a csv, calls the recipient validation API, and outputs a CSV, this program is for you.
When building email applications, developers often need to integrate multiple services and APIs. Understanding email API fundamentals in cloud infrastructure provides the foundation for building robust tools like the bulk validation system we'll create in this guide.
One of the questions we occasionally receive is, how can I bulk validate email lists with recipient validation? There are two options here, one is to upload a file through the SparkPost UI for validation, and the other is to make individual calls per email to the API (as the API is single email validation).
The first option works great but has a limitation of 20Mb (about 500,000 addresses). What if someone has an email list containing millions of addresses? It could mean splitting that up into 1,000’s of CSV file uploads.
Since uploading thousands of CSV files seems a little far-fetched, I took that use case and began to wonder how fast I could get the API to run. In this blog post, I will explain what I tried and how I eventually came to a program that could get around 100,000 validations in 55 seconds (Whereas in the UI I got around 100,000 validations in 1 minute 10 seconds).
Approach | Validations Tested | Time to Complete | Approx. Throughput |
|---|---|---|---|
Bulk async Node.js tool | 100,000 | 55 seconds | ~1,818 validations/sec |
SparkPost UI upload | 100,000 | 1 min 10 sec | ~1,428 validations/sec |
And while this still would take about 100 hours to get done with about 654 million validations, this script can run in the background saving significant time.
The final version of this program can be found here.
My first mistake: using Python
My second mistake: trying to read the file into memory
My initial idea was as follows:

First, ingest a CSV list of emails. Second, load the emails into an array and check that they are in the correct format. Third, asynchronously call the recipient validation API. Fourth, wait for the results and load them into a variable. And finally, output this variable to a CSV file.
This worked very well for smaller files. The issue became when I tried to run 100,000 emails through. The program stalled at around 12,000 validations. With the help of one of our front-end developers, I saw that the issue was with loading all the results into a variable (and therefore running out of memory quickly). If you would like to see the first iteration of this program, I have linked it here: Version 1 (NOT RECOMMENDED).

First, ingest a CSV list of emails. Second, count the number of emails in the file for reporting purposes. Third, as each line is read asynchronously, call the recipient validation API and output the results to a CSV file.
Thus, for each line read in, I call the API and write out the results asynchronously so as to not keep any of this data in long-term memory. I also removed the email syntax checking after speaking with the recipient validation team, as they informed me recipient validation already has checks built in to check if an email is valid or not.
Breaking down the final code
Next Steps
For someone who is looking for a simple fast program that takes in a csv, calls the recipient validation API, and outputs a CSV, this program is for you.
Some additions to this program would be the following:
Build a front end or easier UI for use
Better error and retry handling because if for some reason the API throws an error, the program currently doesn’t retry the call
Consider implementing as a serverless Azure Function for automatic scaling and reduced infrastructure management
I’d also be curious to see if faster results could be achieved with another language such as Golang or Erlang/Elixir. Beyond language choice, infrastructure limitations can also impact performance - we've learned this firsthand when we hit undocumented DNS limits in AWS that affected our high-volume email processing systems.
For developers interested in combining API processing with visual workflow tools, check out how to integrate Flow Builder with Google Cloud Functions for no-code automation workflows.
Please feel free to provide me any feedback or suggestions for expanding this project.



