DEV Community

Cover image for The Notification System That Sent 12,000 Messages at 3 AM
FARHAN HABIB FARAZ
FARHAN HABIB FARAZ

Posted on

The Notification System That Sent 12,000 Messages at 3 AM

I built a notification system for a global SaaS company that sent reminder emails and SMS to users. The first week looked perfect. The second week, 12,000 users got notifications at 3 AM local time. Phones buzzing, inboxes flooding, and support tickets piling up with the same message: why are you spamming me at 3 AM.

The Setup
The platform had users in 47 countries and needed automated reminders that were supposed to land during business hours in each user’s local time. Trial ending in three days should trigger an email at 9 AM. Payment due tomorrow should trigger an SMS at 10 AM. Webinar starting in one hour should trigger a push notification. Account inactive for seven days should trigger a re-engagement email at 2 PM. I built the workflow in n8n, connected it to their database, email service, and SMS gateway, tested with 50 users across three time zones, and deployed.

The 3 AM Disaster
In week two, Monday morning, my phone exploded. The logs showed blocks of sends happening in the middle of the night for multiple regions. Notifications were being sent at around 2 to 4 AM for parts of the US, late evening for parts of Asia, and only looked correct for the UK by coincidence. Total volume crossed 12,000 messages across email and SMS in a single night window.

Why This Happened
My workflow had one fatal assumption. It ran daily at 9 AM server time, then checked all users who needed notifications and sent immediately. The server time was 9 AM UTC. When it was 9 AM UTC, it was 4 AM in New York, 1 AM in Los Angeles, 9 AM in London, 6 PM in Tokyo, and 8 PM in Sydney. Only a slice of Europe got “business hours.” Everyone else got night-time spam.

The Logic I Missed
I thought “send at 9 AM” meant 9 AM in the user’s time zone. I implemented “send at 9 AM” as 9 AM on the server, then broadcast to everyone. What I actually needed was per-user scheduling. For each user, calculate when it is 9 AM in their own time zone, then send at that moment.

The Failed Fix
My first fix was to add a timezone field for users and check it before sending. But the workflow still ran at 9 AM UTC. At 9 AM UTC, most users were not at 9 AM local time, so the system didn’t send to them. The result was the opposite failure: almost nobody received notifications, because the workflow had no mechanism to wake up at the correct hour for each user.

The Real Solution
The system needed timezone-aware scheduling, not a single daily blast.
The first change was storing a real timezone identifier for every user, like America New York or Asia Tokyo, not a raw offset like UTC minus five. That matters because offsets do not handle daylight saving time.
The second change was converting the target local send time into UTC for execution. If a user is in New York and they should receive a 9 AM reminder, the system converts that 9 AM local moment into the correct UTC timestamp and schedules against UTC. Tokyo users will map to a different UTC hour, and that is fine.
The third change was execution cadence. Instead of running once per day, the workflow runs hourly. Every hour, it checks which users have notifications due in that hour window in their local time, converts that to UTC, and sends only to that matching cohort. This spreads the global send load across 24 hours and makes “9 AM local” possible for everyone.

Daylight Saving Time Was the Hidden Landmine
DST shifts break systems that store offsets. A New York user’s “9 AM” maps to different UTC times depending on the season. Using timezone names lets the timezone database handle the shift automatically, so 9 AM remains 9 AM for the user even when the offset changes.

Edge Cases That Matter
Travel breaks assumptions. A user who signs up in New York and later moves to California will still receive notifications at New York’s 9 AM unless they update their timezone. The correct approach is to let users update timezone in settings and optionally prompt them when location changes are detected.
Missing timezone data is common for new users. The practical approach is to guess from IP on signup, ask the user to confirm, and if unconfirmed, default to UTC while marking those sends as lower priority until timezone is set.
DST transitions create ambiguous local times during the fall-back hour. The safest operational rule is to avoid scheduling sensitive messaging in the 1 AM to 3 AM window during DST transition weekends when feasible, or to rely on timezone-aware libraries that disambiguate with explicit offsets.
The international date line makes “today” a different date for different users. The only safe method is always tracking date, time, and timezone together rather than assuming a shared calendar day.

The Transformation
After the fix, New York users received messages at 9 AM local, Tokyo users at 9 AM local, and London users at 9 AM local, but this time it worked by design rather than accident. The middle-of-night sends disappeared.
The Results
Before the fix, roughly 65 percent of notifications went out at the wrong local time, thousands of users received night-time messages, unsubscribes spiked, and support tickets exploded. After the fix, the vast majority of notifications landed inside business-hour windows, night-time sends dropped to near zero, complaints collapsed, and unsubscribe rates normalized.

What I Learned
Server time is never user time. Timezone conversion is not simple math. It includes DST, date line effects, and regional rules. Testing with a few US time zones is not global testing. And timezone math should never be hand-rolled when libraries and timezone databases exist to handle it safely.

The Bottom Line
One oversight, scheduling by server time instead of user time, spammed 12,000 people at 3 AM. The fix was timezone-aware scheduling with per-user conversion and frequent execution windows, so notifications fire when users are awake and ready to engage.

Written by FARHAN HABIB FARAZ, Senior Prompt Engineer and Team Lead at PowerInAI
Building AI automation that adapts to humans.

Tags: timezones, automation, notifications, scheduling, workflows, globalusers

Top comments (0)