User model — streak fields
models/User.ts
How streaks are incremented
Streak incrementing happens insidetaskCompletionService.completeTask(), triggered by POST /api/task-completions. Only the first task completion of the day advances the streak; subsequent completions on the same day have no further effect on current_streak.
services/taskCompletion.service.ts
“Today” is determined by the UTC date. The query in
taskCompletionRepository.findByUserIdToday() compares completed_at against the current UTC date. Users in time zones where midnight differs from UTC may see a streak advance slightly earlier or later than their local midnight.The overnight streak-reset cron job
Incrementing the streak at completion time is only half of the mechanism. The other half is detecting when a user missed a day. This is handled by a scheduled cron job defined insrc/jobs/streakReset.job.ts and started at server boot via startStreakCronJob().
The job runs every day at midnight UTC using node-cron:
jobs/streakReset.job.ts
current_streak is greater than 0 and who has no task_completions row with a completed_at in yesterday’s date window has their current_streak set to 0.
Streak timeline example
After the missed day (Day 4), the cron job resets
current_streak to 0. When the user resumes on Day 5, the streak begins rebuilding from 1. The max_streak of 3 is preserved throughout.