Every developer I know has built at least one "productivity" side project for themselves. Mine was a water reminder app.
Sounds trivial. It was more interesting than I expected.
Here's what I learned from building Thirsty Bot — specifically about the surprisingly hard problem of making notifications that people don't immediately swipe away and disable.
The Core UX Problem: Notification Fatigue
The average Android user receives 46 notifications per day. Most get dismissed without reading.
If your app sends reminders that feel like noise, users will either:
- Swipe and ignore (short term)
- Disable all notifications from your app (permanent death)
So the core challenge of a reminder app isn't "how do I send a notification" — it's how do I send a notification that the user is glad to receive.
What I Tried (And What Worked)
❌ Fixed interval reminders
Every 2 hours, send a reminder. Simple to implement, terrible UX. Users quickly learn to ignore them because they're predictable and interruptive.
❌ Generic messages
"Time to drink water!" gets old after the third notification. Users stop reading after a week.
✅ Smart scheduling within user-defined windows
Let users set their "active hours" (e.g., 8am–10pm). Space reminders evenly across that window. Never send notifications outside of it. This alone dramatically improved retention — users stopped turning off notifications because the app wasn't waking them up.
✅ Rotating, personality-driven messages
I wrote 40+ unique reminder messages with different tones — humorous, motivating, slightly alarming, curious. Examples:
- "Your brain is 75% water. Feed it. 🧠"
- "Dehydration is a silent productivity killer. Drink up."
- "Hey, remember water? It remembers you. 💧"
Engagement went up noticeably. Users mentioned the notifications specifically in feedback.
✅ Immediate progress feedback
After logging a drink, show a satisfying animation and updated progress ring. Make the action feel rewarding.
The Technical Stuff
The reminder scheduling uses Android's AlarmManager with setExactAndAllowWhileIdle() for reliability across Doze mode. This is non-trivial on modern Android — battery optimization is aggressive and will kill WorkManager tasks in background-restricted apps.
For the goal calculation: I settled on the Holliday-Segar formula as a baseline (35ml/kg body weight), with a multiplier for activity level.
For drink type hydration coefficients: water = 1.0, coffee = 0.8, tea = 0.85, juice = 0.9.
What I'd Do Differently
- Add widgets on day one. Users want the progress ring on their home screen.
- Onboarding matters more than I thought. Users who skipped the weight/goal setup were 3x more likely to abandon the app in week one.
- iOS from day one if possible. A significant portion of interested users are iOS-only.
Try It
Thirsty Bot is free on Android: https://play.google.com/store/apps/details?id=com.nextgensoft.thirstybot
Happy to answer questions about the implementation in the comments — notification scheduling on Android is a rabbit hole worth talking about.













