Revealed-Behavior Notification Timing
Trigger reminders off what users actually did, not what they said they'd do — 23.5 hours after last use.
- Difficulty
- Easy
- Time to result
- ~weeks to results
- Steps
- 3
- Confidence
- 90%
For habit reminders, revealed behavior beats stated preference. Duolingo lets users set a reminder time, but the best predictor of when someone will practice is when they practiced the day before — so their winning practice reminder fires 23.5 hours after the previous session, not at a user-chosen time. A second 'streak saver' fires at 10pm if the streak isn't extended, and lands as positive precisely because it protects something users value.
Origin
Found empirically by Jackson Shuttleworth's team after testing more complex timing logic against a simple 23.5-hour rule.
Core principles
- 01Revealed behavior predicts future behavior better than stated intent
- 02Life gets in the way of the time users think they'll practice
- 03Simple behavioral rules beat elaborate timing models
- 04A reminder tied to something users love is received as a gift, not spam
- 05Notification tolerance scales with how much users value the underlying feature
How to run it
- 1
Stop trusting the user-set reminder time
Recognize that when users say they'll practice (e.g. 7pm) is a stated preference that reality overrides. Instead of relying on it, look at their actual behavior.
Pro tip 'The best indicator of when you should practice was when did you practice the day before.'
Watch out User-chosen times feel respectful but underperform because life reliably intervenes.
- 2
Fire the reminder ~24 hours after last use
Send the practice reminder 23.5 hours after the previous day's session, assuming the user was free at that time yesterday and likely free then again.
Pro tip Duolingo tried much more complex timing logic; the plain 23.5-hour rule 'always wins'.
Watch out Don't over-engineer timing — added complexity didn't beat the simple rule.
- 3
Add a value-anchored last-chance nudge
Send a late (10pm) 'streak saver' when the streak isn't yet extended. Because it protects a feature users are emotionally attached to, it reads as helpful, not spammy.
Pro tip Tie the message explicitly to the loved feature ('your streak') so users interpret it as protective.
Watch out The same 10pm notification would feel spammy if it weren't attached to something the user genuinely cares about.
In the wild
Duolingo previously let users set their own reminder time. They switched to firing the practice reminder 23.5 hours after the prior session and tested many more complex timing models against it.
→ The simple 23.5-hour rule 'always wins' over user-set times and more complex logic.
If a user hasn't extended their streak, a 'last chance' message goes out at 10pm — the kind of late notification you'd expect to feel annoying.
→ Users largely perceive it as positive because they care about their streak; it's highly impactful at driving returns.
Common mistakes
Letting users pick their own reminder time
Stated intent ('I'll practice at 7pm') is a poor predictor because life changes; the previous day's actual practice time predicts far better.
Over-engineering notification timing logic
Elaborate models to pick the 'optimal' time repeatedly lost to a flat 23.5-hour-after-last-use rule.
Is it for you?
Best for
Growth/lifecycle PMs designing habit reminders for a daily-use app with a valued core mechanic.
Not ideal for
Apps with no meaningful daily behavior signal to time off, or where a late-night nudge isn't protecting anything users value.
From the transcript
“the best indicator of when you should practice was when did you practice the day before”
“what always wins is 23 and a half hours”
“because people care about their streak their streak is this good thing that they attach positive emotions to that they don't really want to lose…”
From the episode
Behind the product: Duolingo streaks
Jackson Shuttleworth (Group PM, Retention Team)