DEV Community

Cover image for When notifications matter, PWAs start to show their limits
nishchal singh
nishchal singh

Posted on • Edited on

When notifications matter, PWAs start to show their limits

I was getting notifications at 3am.

Users were confused.

I hadn’t changed anything.

That’s when I realized something uncomfortable:

PWAs don’t really understand time the way we expect them to.

Nothing was “broken” in the obvious sense.

Reminders worked. Notifications appeared. Logs looked fine.

But for a productivity app — where reminders and check-ins are the product

“mostly works” isn’t good enough.

This post is about what went wrong, why it wasn’t actually a bug, and why I eventually stopped relying on a pure PWA setup for time-critical notifications.


When PWAs work great (and when they don’t)

If your app needs:

  • in-app banners
  • occasional push notifications
  • background sync when possible

PWAs are an excellent choice.

They’re fast to build, easy to ship, and good enough for many products.

But reminders are different.

A reminder isn’t just a notification.

It’s a promise about time.

And time is where PWAs start to show their limits.


How PWA notifications really behave

When a PWA is open:

  • JavaScript is running
  • the user’s local time is known
  • scheduling logic is predictable

Things feel solid.

The problems start once the app is closed or backgrounded.

At that point:

  • the browser decides when background work runs
  • service workers wake up only under certain conditions
  • push delivery is best-effort
  • timing happens in windows, not exact moments

A “scheduled” notification often looks like this:

  • a backend job checks reminder time
  • timezone logic runs on the server
  • a web push is sent
  • the browser decides when (or if) to wake the service worker
  • the OS eventually shows the notification

Each step makes sense on its own.

Together, they introduce uncertainty.

This isn’t bad engineering.

It’s how browsers are designed.

Browsers optimize for battery life, performance, and security —

not precise scheduling guarantees.


Where things actually broke for me

At first, I assumed this was just a PWA limitation.

Then I wrapped the app with a native Android container and refactored the notification flow.

Some issues still showed up.

That’s when it became clear:

Notification reliability isn’t just about platform choice.

It’s also about how your app understands time itself.

Looking at how mature reminder apps work made the gaps obvious.


What real reminder apps get right

Apps like Google Calendar, TickTick, and Any.do all follow the same principles.


One clear definition of “now”

There is a single authoritative source of current time —

based on device timezone or an explicit user setting.

No guessing.

No hidden defaults.


Store in UTC, schedule in local time

Events are stored in UTC.

They’re converted to local time only for display and scheduling.

This avoids slow, painful bugs around daylight saving and timezone changes.


OS-level scheduling

Reminders are scheduled using system services (for example, AlarmManager on Android).

They’re automatically rescheduled when:

  • the device restarts
  • the timezone changes
  • daylight saving rules shift

The OS owns delivery — not JavaScript.


No dates without context

Any AI planner or automation that generates dates is explicitly told:

“Today is YYYY-MM-DD in this timezone.”

Without this, it’s surprisingly easy to generate reminders in the past or wrong year without noticing.


The real issues in my app

Once I stepped back, the problems were surprisingly basic:

  • timezone defaulting to UTC instead of user locale
  • AI planner not receiving current date and timezone explicitly
  • weekly reminders drifting due to timezone conversion
  • limited control over notification channels and sounds

These aren’t exotic bugs.

They’re the kind that appear only after real users and real time collide.


Why Android behaves more predictably

On Android, the mental model is simpler:

  • the app schedules the reminder locally
  • the OS owns the timing
  • the notification fires when expected

Even if:

  • the app is closed
  • the process is killed
  • the device restarts

Notifications are first-class system features.

That’s why:

  • sound and vibration are consistent
  • notification channels behave correctly
  • widgets are possible
  • background behavior is predictable

This isn’t about Android being “better”.

It’s about using the platform for what it was designed to do.


The setup that finally made sense

For this app, reminders and check-ins aren’t optional.

They are the product.

So the architecture that aligned best was:

Web app (desktop)

  • dashboards
  • insights
  • planning and review

Android app (Capacitor wrapper)

  • native scheduling
  • OS-level notifications
  • background reliability

Same backend.

Same database.

Same product logic.

Different delivery mechanisms — matched to platform strengths.


A simple rule of thumb

  • If notifications are a nice-to-have → PWAs are usually fine
  • If notifications are a core promise → let the OS handle timing

That distinction would have saved me weeks.


Final thought

PWAs aren’t unreliable.

They’re just not designed to guarantee time.

Native platforms are.

Once you align product expectations with what a platform can realistically promise, a lot of confusion — and frustration — disappears.


Quick question for you

  • Have you faced random notification timings in PWAs?
  • How are you handling scheduled reminders today?
  • Would you still choose a PWA if notifications were critical?

I’m genuinely curious how others are solving this.


Live app (still evolving):

👉 https://wio-dev.vercel.app

Top comments (0)