Automation Engineering

Four timed messages per registrant, exactly once, with no message broker

A registration platform for a live hiring event — a public page, WhatsApp OTP verification, an admin console, and a time-aware automation engine running its own delivery queue on serverless infrastructure.

Client
ExcelR

What was the problem?

Registrations had to be real rather than spam, and every registrant had to receive a sequence of reminders at exactly the right moment on the channel they read. The real engineering challenge: guarantee each person gets each message exactly once, on serverless infrastructure with no message broker, no always-on worker, and a 30-second execution ceiling.

What made it hard

Commercially

  • A duplicate message to a real applicant is a visible, brand-damaging failure
  • The event date is fixed; late registrants still need the full sequence

Technically

  • Serverless infrastructure with no message broker, no always-on worker and a 30-second execution ceiling
  • A cron tick and an admin button-click can fire in the same second
  • A run can crash mid-flight, leaving claimed work stranded
  • A message can send successfully while the status write fails

Operationally

  • Admins needed per-person delivery visibility and the ability to push any message batch manually
  • Registration had to be switchable on and off

At scale

  • Batches large enough that the queue must drain across multiple invocations rather than one long-running process

Security

  • OTPs are an obvious abuse target — by phone, by IP and by brute force
  • No credential could reach the browser
  • The scheduler endpoint is publicly addressable

What we built

An applicant verifies a WhatsApp OTP before they can register. The submission is normalised, window-checked and written inside a transaction blocking duplicates by phone and email at once. A welcome WhatsApp, a branded email, an admin alert and an n8n webhook fire immediately, and the lead enters the automation queue where the engine owns it for 48 hours. Admins oversee everything from a console with search, filters, sorting, cursor pagination, CSV export, per-person delivery status and manual batch push.

What it does

  • WhatsApp OTP verification

    Six-digit OTP via Infobip with HMAC-hashed storage, expiry, cooldown and rate limits.

  • Dual-key duplicate prevention

    Transactional blocking by phone and email simultaneously.

  • Four-message automation sequence

    Across WhatsApp and email, with per-person, per-channel delivery state.

  • IST-aware scheduling

    All timing logic computed in IST regardless of where the server runs.

  • Quiet hours

    WhatsApp never fires between 9 PM and 8 AM; messages are held and released at 8 AM.

  • Adaptive delays

    A message normally sent an hour after signup compresses to 10 then 5 minutes for last-minute registrants.

  • Cutoffs and exclusions

    Messages that no longer make sense are skipped with a recorded reason.

  • Message sequencing

    A later reminder waits for the earlier message to actually complete, so messages never arrive out of order.

  • Admin console

    Search, filters, sorting, cursor pagination, CSV export and manual batch push.

  • Registration window switch

    Registration can be opened and closed operationally.

  • Run history and delivery reports

    Runs grouped by day with per-message delivery reporting.

  • n8n webhook

    Fires on registration for downstream workflow automation.

Engineering decisions

Choices that could have gone another way, and what each one bought.

  1. The database is the queue

    Every lead carries a delivery record for each message and channel, moving through pending → sending → sent, failed or skipped. There is no separate broker to fall out of sync with the data.

    Why it matters. Serverless with no broker and no always-on worker is a genuinely constrained environment. Making the data the queue removes an entire class of consistency bugs rather than adding infrastructure.

  2. Transactional claiming as distributed locking

    Before any send, the worker claims that lead's channel inside a Firestore transaction. Two workers can never claim the same message.

    Why it matters. A cron tick and an admin button-click firing in the same second cannot double-send to a real person — the guarantee is structural rather than a race the code tries to win.

  3. Cursor checkpointing and time-budget governance

    Each message type persists its own scan position. A tick sends one batch, saves the cursor and returns, and the runner continuously checks its remaining budget, refusing to start a batch without enough headroom to finish and respond cleanly.

    Why it matters. This is what keeps the runner inside a hard 30-second platform timeout instead of dying halfway through a batch — the queue drains across ticks rather than demanding one long process.

  4. A sent message with a failed status write extends the lock

    In the one genuinely dangerous case — the message went out but the database write recording it did not — the lock is extended rather than released.

    Why it matters. Releasing the lock would let the next tick resend. Extending it means a database blip can never cause a duplicate message to a real person.

  5. Scheduling that behaves like a person would

    All logic computed in IST regardless of server location. WhatsApp never fires between 9 PM and 8 AM. A message normally sent an hour after signup compresses to 10 then 5 minutes for last-minute registrants, and messages that no longer make sense are skipped with a recorded reason.

    Why it matters. Exactly-once delivery is the engineering guarantee, but the scheduling rules are the part the recipient actually feels — someone registering on the morning of the event still gets everything in time, and nobody registering on event day is told the event is tomorrow.

  6. OTPs that are never stored

    Only HMAC-SHA256 hashes, generated with a CSPRNG and compared in constant time, behind per-phone and per-IP hourly caps, resend cooldowns, attempt limits and single-use verification markers with a short TTL.

    Why it matters. An OTP endpoint is one of the most attacked surfaces on any public form, and a plaintext OTP store turns a database read into account takeover.

Technical detail

Collapsed by default. Open whichever part you are evaluating.

Frontend
  • Next.js 14 (App Router)
  • TypeScript
  • Tailwind CSS
  • React Hook Form + Zod
Backend
  • Next.js API routes on serverless with a 30-second execution ceiling
Database
  • Firebase Firestore with deny-all client rules and server-only writes
Authentication
  • HMAC-signed admin session cookies with timing-safe comparison
  • WhatsApp OTP for applicants
Authorization
  • Bearer-token protected scheduler endpoint
Background processing
  • Database-as-queue with transactional claiming, stale-claim recovery, global run lock, cursor checkpointing and time-budget governance
Caching
  • Redis (Upstash)
Messaging
  • Infobip WhatsApp API
  • Nodemailer / SparkPost email
Deployment
  • Vercel
Monitoring
  • Run history grouped by day
  • Per-message delivery reports
  • Failure alerting by email

Frontend
  • Next.js 14
  • TypeScript
  • Tailwind CSS
  • React Hook Form
  • Zod
Backend
  • Next.js API routes
  • TypeScript
Database
  • Firebase Firestore
Cloud
  • Vercel
  • Redis (Upstash)
Integrations
  • Infobip WhatsApp API
  • Nodemailer / SparkPost
  • n8n
Tools
  • Vitest

Authentication
  • WhatsApp OTP gate for applicants
  • HMAC-signed admin session cookies compared in timing-safe fashion
Authorization
  • Bearer-token protected scheduler endpoint
  • Server-only Firestore writes
Data protection
  • OTPs are never stored in plaintext — only HMAC-SHA256 hashes, generated with a CSPRNG and compared in constant time
  • Every credential stays server-side
  • Firestore rules deny all direct client access
Abuse prevention
  • Per-phone hourly caps
  • Per-IP hourly caps
  • Resend cooldowns
  • Attempt limits
  • Single-use verification markers with short TTL
Auditability
  • Per-person, per-channel delivery records
  • Run history grouped by day
  • Complete event log of everything sent
Privacy
  • Phone numbers normalised to E.164 and stored server-side only

Mechanisms

  • Database-as-queue with a per-recipient, per-channel state machine
  • Transactional claiming as distributed locking
  • Stale-claim recovery after a 5-minute expiry
  • TTL-based owner-tokened global run lock
  • Per-message-type cursor checkpointing
  • Time-budget governance before starting each batch
  • Provider-level batching with per-recipient result mapping
  • Write-retry with exponential backoff
  • Bounded concurrency pools
  • Idempotent runs

Failure scenarios handled

  • A cron tick and an admin button-click fire in the same second
  • A run crashes mid-flight leaving work claimed
  • Overlapping scheduler triggers
  • The 30-second execution ceiling is reached mid-batch
  • One invalid number inside a 40-recipient batch
  • A message sends successfully but the status write fails
  • A run is re-triggered after a partial completion

Idempotency. Every run is safe to re-run. Already-delivered leads are skipped automatically, and claiming happens inside a transaction so two workers can never claim the same message.

Recovery. Claims expire rather than needing cleanup, so a crashed run's leads are reclaimed on the next tick instead of being stranded. Cursors mean a tick resumes exactly where the previous one stopped. And in the one genuinely dangerous case — a message sent but its status write failing — the lock is extended rather than released, so a database blip can never cause a duplicate message to a real person.

Before and after

Before

  • Registration open to unverified and duplicate entries
  • No systematic reminder sequence
  • No record of who had been contacted on which channel

After

  • WhatsApp OTP required before a registration can exist
  • One record per person, enforced transactionally by phone and email
  • Four timed touchpoints delivered exactly once per registrant
  • Per-person, per-channel delivery status visible in an admin console

The build, by the numbers

What was built, at what scale. These describe the system's size, not its business results.

automated tests
122automated testsCovering OTP security, scheduling mathematics, cron budgeting and provider integration
timed message types
4timed message typesDelivered across WhatsApp and email over 48 hours per registrant
recipients per API request
40recipients per API requestBatched WhatsApp sends with results mapped back per recipient
external systems integrated
5external systems integratedFirestore, Infobip, SparkPost, Upstash Redis and n8n
days to delivery
~11days to deliveryFully deployed and live under an urgent client timeline

What changed as a result?

Delivered in roughly 11 days under an urgent timeline, fully deployed and live, with 122 automated tests covering OTP security, phone normalisation, IST scheduling mathematics, cron budgeting, admin sessions and provider integration.

  • Built exactly-once message delivery on serverless with no message broker
  • Blocked fake registrations with a mandatory WhatsApp OTP gate
  • Delivered four timed touchpoints per registrant across two channels
  • Made every run safe to re-run, with automatic recovery from crashed runs
  • Shipped and deployed in roughly 11 days under an urgent timeline

Why does this matter in EdTech & training?

Training providers usually have the harder half solved already: an audience that trusts them. What leaks is the path from interested to enrolled. WezvaTech reaches over ten thousand learners; the work was making the site convert that reach rather than admire it.

  • A large audience and a thin enrolment path

    Reach does not convert on its own. Course pages, a visible enrolment route and instant-response contact options are what turn followers into paying learners.

  • Placement claims nobody can verify

    Every training provider claims placements. The ones that convert show named outcomes, real project work and reviews a prospect can check, rather than a percentage with no source.

  • Enquiries arriving where nobody is watching

    Technical learners message on WhatsApp and expect a fast reply. An enquiry that waits overnight is usually an enrolment lost to whoever answered first.

  • No visible difference between courses

    When a flagship bootcamp, an internship and a webinar all look alike, prospects default to the cheapest. Distinct pages with distinct outcomes let people self-select correctly.

More on what we build for EdTech & training

Need something like this for EdTech & training?

Tell us what is slowing the business down and we will tell you whether software is the right fix. If it is not, we will say so.

Ask a Quick Question on WhatsApp

Free 30 minutes · no obligation

WhatsAppCall