Describe the data model and backend logic for a daily login bonus.

This tests streak state machines and calendar edge cases. A strong answer stores last_login_utc and streak_count, uses UTC day buckets, resolves timezones per user tz, and needs no leap-year logic.
Naive 24-hour windows break during DST shifts.
What's really being asked
The interviewer wants to see if you can translate a product concept into a minimal, correct data model and state machine. This is a beginner-level question, but it quickly reveals whether you think about idempotency, time, and user-specific context. The psychology of streaks is powerful; Duolingo saw a 60 percent surge in user commitment after introducing iOS streak widgets, and loss aversion means users feel the pain of breaking a streak roughly twice as much as the pleasure of starting one. Because of this emotional weight, backend accuracy matters deeply.
The full answer
First, the core table: a user_streaks table with user_id, last_login_at as UTC timestamp, current_streak as integer, and maybe longest_streak. Second, the grant logic must be idempotent: when the user logs in, compute the current UTC date and compare it to the stored last_login_utc date. If it is the same UTC day, do nothing. If it is exactly one day later, increment current_streak. If it is more than one day later, reset current_streak to one. Third, timezone handling: never trust the client clock for security, but accept a user_timezone string. The daily boundary for that user is midnight in their timezone, converted to UTC on the server. Alternatively, run a scheduled job at each user's local midnight. Fourth, leap years are a non-issue because UTC day boundaries and date math libraries handle February 29 automatically; you should not write custom leap-year logic. Fifth, mention a streak_freezes or grace_period table if the product allows it, because loss aversion is strong and a 60 percent commitment lift is fragile if a single server hiccup breaks a long streak.
The mistakes people make
Storing timestamps in local time without timezone offsets. Using a naive 24-hour rolling window instead of calendar days, which breaks during daylight saving transitions and causes streaks to expire at weird times. Forgetting idempotency so that retrying a login request double-increments the streak. Writing custom leap-year detection instead of relying on standard date libraries. Ignoring the distinction between the user's local day and the server's UTC day, which leads to off-by-one errors for half the planet.
What usually comes next
How would you handle streak freezes or grace periods after a missed day? How would you backfill streak data if you add this feature retroactively? How would you scale the daily check for millions of users without hitting a single database row per user at exactly midnight? What happens if the user travels and their timezone changes while a streak is active?
A concrete example
Suppose a user in Tokyo with timezone Asia/Tokyo logs in at 11 PM JST on March 1. That is 2 PM UTC on March 1. The server records last_login_utc as 2024-03-01 14:00:00Z. They log in again at 1 AM JST on March 2, which is 4 PM UTC on March 1. Because both fall within the same UTC day, the streak should NOT increment yet. If they log in at 1 AM JST on March 3, that is 4 PM UTC on March 2. The server compares UTC dates March 2 versus March 1, sees a one-day gap, and increments the streak. Leap year 2024 means February 29 exists, but the date library simply maps 2024-02-29 to 2024-03-01 correctly with no custom code.
Interview question
Which approach correctly models the backend logic for a daily login streak while avoiding common timezone and idempotency bugs?
- a.Store last_login_utc, current_streak, and user_timezone; use calendar-day buckets aligned to the user's local midnightCorrect
- b.Store last_login_utc and current_streak, then derive the user's timezone from their device clock on each request
- c.Store only the last login timestamp in local time and increment the streak whenever 24 hours have elapsed
- d.Store a daily_login boolean and reset all streaks at a single global midnight UTC
Why? this is the answer
Option A is correct because the card specifies storing UTC timestamps and a user_timezone, then evaluating logins against calendar-day boundaries set to the user's local midnight to handle DST and idempotency. Option C is tempting but wrong because local timestamps and 24-hour rolling windows break during daylight saving transitions and can double-count retries.
Just read this? Test yourself on what you have been reading.
Read the original → smashingmagazine.com
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on growth — each one lists the topics its interview covers.
See open roles