All articles
SaaSFebruary 11, 2026·10 min read

How We Built Qverio: Lessons from Launching a Real-Time Email Verification SaaS

Soumik Sengupta

Soumik Sengupta

Full-Stack Developer · 10+ years building on Laravel, WordPress & SaaS

Key Takeaways

  • 1SMTP verification has three major complications: catch-all domains (~15–20% of business email), rate limiting by major providers, and timeout handling.
  • 2Priority queues (realtime / bulk-high / bulk-low) ensure premium users never wait behind free users processing large lists.
  • 3Track credits in your own database — not Stripe. Stripe is source of truth for billing events; your DB is source of truth for balances.
  • 4The biggest mistake: spending 3 weeks on complex onboarding that users ignored. They went straight to uploading a file.
  • 5Launch with a smaller MVP than you think you need. Validate demand before building the full platform.
SaaSLaravelProduct DevelopmentFounder Story

Qverio is a real-time email verification SaaS. You submit a list of email addresses — or query one via API — and it tells you immediately whether each address is valid, the risk level, and the MX/SMTP details. It's used by email marketers, lead generation teams, and SaaS companies to clean their lists before sending.

This is the unfiltered version of how I built it: the technical decisions, what I got wrong, what I'd do differently, and the specific challenges that turned out to be harder than expected. If you're planning to build a data processing SaaS, there's a lot here that applies directly.

Why I Built It

The email verification market has plenty of players — ZeroBounce, NeverBounce, Hunter.io, Mailfloss. I didn't build Qverio because I thought the market was underserved. I built it because I kept getting asked by clients to integrate email verification into their platforms, and the existing APIs all had friction: complex pricing tiers, slow response times, or rate limits that made real-time single-address lookup frustrating.

I also wanted a project that would teach me something. SMTP verification isn't something most developers have done — it requires understanding email infrastructure at a level that goes well beyond "send an email." I found that genuinely interesting.

The Technical Architecture

The core stack: Laravel 11 for the application layer, MySQL for data storage, Redis for queue management and rate limiting, Alpine.js for the frontend, Stripe for billing, and a DigitalOcean Droplet for hosting.

The verification pipeline has three stages:

1. Syntax & Format Check

Basic regex validation plus RFC 5322 compliance. This is trivial but important to do first — no point running DNS lookups on 'not-an-email'.

2. DNS & MX Record Check

Query the domain's DNS records to verify it exists and has MX records pointing to a mail server. A domain with no MX records cannot receive email. This eliminates a large percentage of invalid addresses quickly and cheaply.

3. SMTP Verification

Connect to the mail server, issue RCPT TO: commands, and observe the response. A 250 response means the mailbox exists. A 550 means it doesn't. This is the expensive part — it requires an actual network connection to the remote server.

The Hardest Part: SMTP Verification at Scale

SMTP verification sounds straightforward but has three major complicating factors:

Catch-all domains. Some mail servers accept RCPT TO for any address at their domain, even if the mailbox doesn't exist. Gmail does not do this; most large corporate domains do. When your server says "yes" to every address, SMTP verification can't tell you if the specific mailbox is real. I mark these as "accept-all" and score them with a confidence rating based on domain age, MX provider, and historical data.

Rate limiting by mail servers. Major providers — Microsoft 365, Google Workspace, Yahoo — aggressively throttle and block SMTP verification requests. If you hammer their servers with too many RCPT TO commands from a single IP, they'll block you. I maintain a pool of outbound IPs and implemented per-domain rate limiting in Redis to stay under detection thresholds.

Timeout handling. Some servers respond in 50ms. Some take 8 seconds. Some never respond at all (greylisting, firewalls). I settled on a 6-second timeout with three retry attempts on different IPs before marking an address as "timeout/unknown." This balances accuracy against queue throughput.

The Queue Architecture

Bulk list verification is where queuing becomes critical. A user uploading 50,000 emails can't wait for synchronous processing — they get a "we're processing your list" confirmation and the work happens in the background.

I use Laravel Horizon with Redis queues. Each verification job is dispatched to one of three priority queues: realtime (single-address API lookups), bulk-high (premium plan users), and bulk-low (free/basic plan users).

The priority queue system means premium users never wait behind a free user who uploaded 100,000 emails. This is a critical design decision for any SaaS that processes variable-size workloads.

Horizontal scaling:

Worker processes run on separate server instances from the web layer. I can spin up additional worker instances during high load without touching the web servers. Laravel Horizon makes this trivial — it's one of the best pieces of Laravel's ecosystem.

Billing with Stripe: Credits vs. Subscriptions

I went with a hybrid model: subscriptions that include a monthly credit allocation, plus pay-as-you-go credits that can be purchased at any time. This is common in API-first products and Stripe handles it, but it took significant setup.

The key architectural decision: I track credits in my own database, not in Stripe. Stripe is the source of truth for billing events (subscriptions created, payments succeeded/failed), but my database is the source of truth for credit balances. This gives me flexibility — I can issue bonus credits, apply discounts, or implement referral rewards without touching Stripe's metering system.

Stripe webhooks update the database on payment events. Every verification job decrements the credit balance atomically (MySQL transactions) to prevent double-spending under concurrent requests.

The Mistakes I Made

Honesty about what went wrong is more useful than a clean success story:

  • Under-estimated the catch-all problem: I thought it would be a small edge case. It's not — roughly 15-20% of business email domains are catch-all. My initial result accuracy was misleadingly high because I was calling catch-all domains 'valid.' I had to add a whole scoring system and risk classification layer after launch.
  • Built a complex multi-step onboarding before validating demand: I spent three weeks building an elaborate onboarding flow with a guided tour, sample data, and progress tracking. The first five users ignored all of it and went straight to uploading their list. I simplified it down to 'upload a file or paste emails, get results.' Classic over-engineering.
  • No rate limiting on my own API at launch: A user wrote a script that hit the API 10,000 times in 20 minutes during the free trial period. It used up significant server resources and caused latency for other users. I added rate limiting immediately, but I should have had it from day one.
  • Wrong pricing tier structure: I launched with three tiers: 1,000 / 10,000 / unlimited. The 'unlimited' tier was too expensive for the value it offered, so no one bought it. Most customers landed on the middle tier. I restructured to 5,000 / 25,000 / 100,000 credits and conversion improved significantly.

What I Got Right

  • Building the API first: Qverio has a REST API from day one. The dashboard is essentially a UI on top of the same API. This made it easy for technical users to integrate immediately, and it forced clean design of the core functionality.
  • Structured result data: Each verification returns a consistent JSON object with status, sub-status, free_email flag, disposable flag, role-based flag, MX provider, and a confidence score. Users know exactly what they're getting and can build downstream logic against the structure.
  • Detailed activity log: Every API call is logged with timestamp, email (hashed for privacy), result, processing time, and credit used. Users can audit their usage and I can debug issues without guessing.

What I'd Do Differently

If I started Qverio today, knowing what I know now:

  1. 1Launch with a much smaller MVP — just single-address verification, no bulk upload, no dashboard. Validate demand before building the full platform.
  2. 2Spend more time on the catch-all classification system before launch, not after.
  3. 3Implement usage-based pricing with Stripe Meters from the beginning rather than the custom credit system — it's less flexible but much simpler.
  4. 4Set up infrastructure monitoring (Uptime Robot, Sentry) before the first user, not after the first outage.
  5. 5Write integration docs on day one. Developer users will not use your product if they have to figure out the API from the response structure alone.

The Takeaway for SaaS Builders

The technical challenges of building Qverio were significant but solvable. The harder lessons were about product decisions — scope, pricing, onboarding, when to launch. Every week spent building features that users don't use is a week not spent talking to potential customers.

If you're building a SaaS product and want to avoid the mistakes I made, the most valuable thing I can offer is direct experience. I've now built three SaaS products from scratch and helped dozens of founders scope and architect theirs. That's a lot of hard-won patterns to learn from.

Building a SaaS product?

I can take your idea from spec to production — architecture, billing, auth, API design, everything. Tell me about your product and I'll put together a scope estimate.

Frequently Asked Questions

How does email verification work technically?
Email verification works in three stages: (1) Syntax check — validating the email format against RFC 5322. (2) DNS/MX record check — verifying the domain exists and has mail servers configured. (3) SMTP verification — connecting to the mail server and issuing RCPT TO commands to check if the specific mailbox exists. A 250 response means valid; 550 means invalid.
What is a catch-all email domain?
A catch-all domain accepts RCPT TO for any email address at that domain, even if the mailbox doesn't exist. Around 15–20% of business email domains are configured this way. This means SMTP verification returns 'valid' for any address at those domains, regardless of whether the mailbox actually exists. These addresses require additional scoring based on domain age, MX provider, and historical data.
How do you build a SaaS with credit-based billing?
The recommended approach: use Stripe for billing events (subscriptions, payments, invoices) but track credit balances in your own database. Credits are decremented atomically using database transactions to prevent double-spending. Stripe webhooks update your DB on payment events. This gives you flexibility to issue bonus credits, referral rewards, and custom plans without fighting Stripe's metering system.
What tech stack is best for building a SaaS product?
For most SaaS products: Laravel (framework), MySQL (database), Redis (queues and rate limiting), Laravel Horizon (queue monitoring), Stripe + Laravel Cashier (billing), Alpine.js or Vue.js (frontend), Laravel Forge + DigitalOcean (hosting), Sentry (error tracking), and Uptime Robot (monitoring). This stack gets you from zero to production in 6–10 weeks for most products.
How do you scale a SaaS application?
Horizontal scaling strategy: separate web servers from queue workers so each can scale independently. Use Redis for session storage and rate limiting. Implement queue priority levels so premium users get faster processing. Use read replicas for database-heavy reporting. Add a CDN for static assets. Most SaaS products don't need microservices — a well-structured Laravel monolith scales to millions of users with proper infrastructure.

Have a project in mind?

I work with businesses worldwide on Laravel applications, WordPress sites, SaaS products, and browser extensions. Get a free quote — no obligation.

Get a free quote

More Articles