I'm using setTimeout in JavaScript for a 30-minute countdown, but it consistently finishes roughly 30 seconds after the same timer on my phone. Is this expected behavior, and what's the right way to make the countdown more accurate?
3 Answers
Don’t count timer ticks as the source of truth. Save the target end time once, then calculate the remaining time from Date.now() each time you update the display. That way, if a callback runs late, the next update corrects itself instead of accumulating the delay from every tick.
Browser throttling, background-tab restrictions, and device sleep can all pause or slow timers. If this is running in a Node.js process, those browser-specific restrictions generally aren’t involved, but the event loop can still delay callbacks when the process is busy.
Yes, this is expected. setTimeout only guarantees that the callback won’t run before the requested delay; it doesn’t guarantee it will run exactly then. The browser may delay it while handling other work, and background tabs or a sleeping device can introduce even more delay. It’s better treated as a scheduling request than a precision timer.

For a 30-minute timer, around 30 seconds of drift can happen, especially if the page is inactive or the device is busy.