Why Background-Tab Timers Drift (and How Tickline Fixes It)
Updated 2026-07-27
If you've ever set a browser timer, switched to another tab for a few minutes, and come back to find it several seconds behind — or worse, still showing the wrong number — you've run into background-tab throttling. This isn't a bug. It's a deliberate design choice by every modern browser, and it's the single biggest reason naive JavaScript timers become unreliable.
The naive implementation
The simplest way to build a timer is to call setInterval every second and subtract one from a counter:
let seconds = 300;
setInterval(() => {
seconds--;
render(seconds);
}, 1000);This works fine in a focused tab. It falls apart the moment the tab is backgrounded.
What browsers actually do
When a tab loses focus, browsers throttle timers aggressively to save battery and CPU. Chrome, Firefox and Safari all cap setInterval and setTimeout callbacks in background tabs to roughly once per second, and after around 5 minutes of inactivity Chrome throttles further — in some cases to once per minute. On mobile it's even more aggressive; iOS Safari will suspend timers entirely when the browser is not in the foreground.
A naive timer decrementing a counter simply misses ticks. When the tab is focused again the counter is wrong by the exact number of skipped ticks.
End-timestamp anchoring
The fix is elegant and old: don't count ticks, compute the remaining time from a fixed end-timestamp. When the user presses Start, you record the wall-clock time at which the timer should end:
const endAt = Date.now() + durationMs;
function tick() {
const remaining = endAt - Date.now();
render(remaining);
if (remaining > 0) requestAnimationFrame(tick);
else fireAlarm();
}Now the render loop can fire at any rate — 60fps in the foreground, once per second in the background, or not at all while the tab is throttled. Because every frame computes endAt - Date.now(), the moment the tab regains focus the display jumps to the correct value. Zero drift.
Firing the alarm on time
Anchoring the display is only half the problem. If the alarm relies on a setInterval tick, a heavily throttled tab will still fire it late. The complete fix uses two mechanisms:
- Compute remaining from the end-timestamp on every tick so the display never drifts.
- Fire the alarm the moment the tab regains focus if the remaining time has passed while the tab was throttled — the browser's visibility-change event tells you when this happens.
For scheduled notifications independent of tab focus, add a ServiceWorker or use the platform's Notifications API. Tickline uses both: end-timestamp anchoring for the visible countdown, and OS-level notification permission for delivery when the browser itself is minimized.
What this means for you
If a timer you're using on the web is drifting, it's almost certainly built the naive way. Every countdown on Tickline — from the custom timer to Pomodoro to the preset pages — uses end-timestamp anchoring. Switch tabs, dim your screen, come back an hour later: the number will be right.
Related tools
Next guide
Study Timer Workflows That Actually Hold UpHow to structure a study session with timers: choosing block lengths, spacing breaks, handling long revision days, and avoiding the common traps.
More guides
- How the Pomodoro Technique Works (and How to Time It Right)
- Best HIIT Interval Lengths for Beginners
- Study Timer Workflows That Actually Hold Up
- Using a Classroom Timer Without Stressing the Room
- Kitchen Timing Basics: Why Recipe Times Are Only a Starting Point
- What People Actually Use Event Countdowns For
- How Long Should a Meditation or Breathing Session Be?
- AMRAP vs EMOM vs Tabata: Choosing a Workout Structure
- Timing Meetings, Standups and Presentations
- Nap Lengths and Sleep Timing, Explained
- How to Choose the Right Timer Length