Key Takeaways
- Go is the right language for high-throughput email verification because goroutines and channels make worker pools trivial to implement.
- The pattern is a job channel feeding N workers calling the v2 verify endpoint concurrently, with results streaming to an output channel.
- Production deployments need three additions: context cancellation, retry with exponential backoff, and rate limiting that respects the API quota.
- A 16-worker pool processes roughly 100,000 addresses in 8 to 12 minutes against the v2 endpoint, well within rate limits.
Go is the language of choice for any email verification workload that needs to process more than a few thousand addresses. Goroutines and channels collapse the complexity of concurrent HTTP calls into a few dozen lines of code, and the standard library handles everything else: context cancellation, timeouts, JSON parsing, and graceful shutdown. This guide walks through the production pattern that takes a list of email addresses and returns verification results through the v2 API at full network throughput.
The complete reference implementation is documented on the verify email with Go integration page, including framework-specific patterns for net/http, fasthttp, and the Go standard library client.
The v2 Endpoint
Before writing Go, confirm the endpoint works against a known address. The v2 verify endpoint accepts the email as a query parameter and returns a JSON document with all the fields needed for decision logic.
The status field is the primary decision input. Passed indicates the mailbox exists and accepts mail. Failed means the mailbox does not exist, syntax is invalid, or the domain has no MX server. Unknown covers greylisting and transient SMTP errors. The boolean flags surface category-specific risk signals that warrant separate handling.
The Verification Client
The Verifier struct wraps an http.Client with a timeout, the API key, and the base URL. A single instance is safe for concurrent use across goroutines because http.Client is internally synchronized.
Two design choices deserve attention. The Verify method takes a context.Context as its first parameter, which is idiomatic Go for cancellable operations. Callers can cancel the request through context cancellation, which propagates to the HTTP client and aborts the in-flight call. The http.Client has a hard 10-second timeout independent of context, which protects against deadlocked requests when callers pass a non-cancelling context.
The Concurrent Worker Pool
For bulk verification, fan out the work across N goroutines pulling from a job channel. Each worker calls Verify concurrently and writes results to an output channel. The pattern handles 100,000 addresses in 8 to 12 minutes with 16 workers, comfortably within the v2 endpoint rate limits.
The Pool method spawns N worker goroutines and returns an output channel that closes when all workers have finished. The verifyWithRetry helper handles transient network errors with exponential backoff and respects context cancellation throughout. Callers feed jobs into the input channel, range over the output channel, and the pool handles the rest.
Driving the Pool From a CSV File
The main function ties together input reading, the worker pool, and output writing. Read addresses from a CSV, push them into the job channel, range over outcomes as they arrive, and write each one to the output CSV.
The signal.NotifyContext call propagates SIGINT and SIGTERM into the context, which means Ctrl+C cleanly cancels in-flight verifications and flushes the output CSV before exiting. This matters for long-running bulk jobs because partial results stay on disk even when the operator interrupts the run.
For broader integration patterns across other languages, the email verification integrations hub covers Node.js, Python, Ruby, Java, PHP, and the rest of the supported stacks. New developers can grab 100 free email verification credits on signup to test the integration before committing to a plan.
Frequently Asked Questions
How many concurrent workers should I run?
Sixteen is a good default for bulk verification. The v2 endpoint handles concurrency comfortably and the network is rarely the bottleneck. Increasing beyond 32 workers tends to surface API rate limits without measurable throughput improvement.
What about HTTP/2 connection multiplexing?
Go's net/http client uses HTTP/2 automatically when the server supports it. Verification calls share connections through the pool, so explicit HTTP/2 configuration is not required. The default behavior is correct.
How do I avoid double-counting on retries?
Verification calls are idempotent at the application layer. The same email returns the same result within the cache TTL, and retries on transient errors do not double-charge against the API quota because the underlying call only counts on successful completion.
Can I use this pattern for real-time signup verification?
Yes. For real-time use, skip the worker pool and call Verify directly from the request handler. Wrap the verifier in middleware similar to net/http handlers and the same retry and timeout behavior applies.