BE AWESOME
Settings
Web Tools
📅 August 3, 2026 · ⏱️ 5 min read

Timer & Stopwatch: Why setInterval Alone Isn't Trustworthy

Real timestamp math instead of tick-counting, so a stopwatch left running in a backgrounded tab still reports genuinely accurate time.

This post is about Timer & Stopwatch: Why setInterval Alone Isn't Trustworthy
Try the Timer & Stopwatch →

A stopwatch counts up with lap-splitting. A countdown timer counts down to zero with a visual progress bar. They're related but genuinely distinct tools — one measures elapsed time with no predetermined end, the other measures remaining time against a duration you set up front — and I built both into one tabbed interface rather than as two separate pages, since anyone reaching for one of these often wants the other on a different day.

A running timer can't trust setInterval alone

The naive way to build a stopwatch is incrementing a counter on a recurring interval callback, and that approach drifts over time, because interval timers in a browser aren't guaranteed to fire at perfectly precise intervals, especially once a tab is backgrounded or the system is under load. A stopwatch that's supposed to show accurate elapsed time can't just count ticks — it has to record a real start timestamp and continuously calculate elapsed time as the difference between now and then, using the interval purely to trigger a redraw of the display rather than as the actual source of truth for how much time has passed. Get that backwards and a stopwatch left running for twenty minutes can end up measurably wrong, which defeats the purpose of a tool whose entire job is accurate timekeeping.

Laps needed to record without ever interrupting the running clock

Clicking Lap has to capture the current elapsed time as a snapshot in a running list without pausing or resetting the underlying stopwatch in any way — the whole point of lap-splitting is reviewing intermediate times while the clock keeps running uninterrupted. That meant lap recording is purely additive: read the current elapsed time, append it to a list, and let the actual timing mechanism continue completely unaffected. It sounds obvious stated plainly, but it was worth being explicit about during the build, since a bug that briefly paused the clock during a lap capture — even by a few milliseconds — would be a real accuracy problem for exactly the use case, tracking split times during a physical activity, this feature exists for.

Resetting needed to feel deliberate, not accidental

Reset wipes the stopwatch back to zero and clears every recorded lap, which is a genuinely destructive action if it happens by accident in the middle of tracking something that actually mattered. I thought about the button's placement and visual weight specifically to keep it clearly distinguished from Start, Stop, and Lap, since those three get clicked far more often during normal use and a misplaced Reset sitting too close to them is exactly the kind of layout mistake that costs someone a real recorded session to a stray misclick. It's a small interface detail, but for a tool whose entire output is data you can't regenerate after the fact, protecting against an accidental destructive click mattered more here than it would for a tool where a mistake costs nothing to redo.

The countdown timer's progress bar had to be genuinely proportional

The visual progress bar draining as a countdown runs needed to represent actual proportional remaining time, not just an approximation that looks roughly right. A bar that drains at a visually pleasing but slightly inaccurate rate would create a mismatch between what someone sees and what the numeric countdown actually says, which is a small inconsistency that erodes trust in the whole tool the moment someone notices the bar and the numbers disagree even slightly near the end of a countdown. Tying the bar's width calculation directly to the same elapsed-time math driving the numeric display, rather than animating it independently, was the only way to guarantee they'd never visibly drift apart from each other.

Leaving the tab and coming back had to just work

Someone starting a countdown timer and switching to a different tab for most of its duration is the single most likely real usage pattern for this tool, and it needed to keep accurate time through that without any special handling on the visitor's part. Because both the stopwatch and the countdown timer are built on real timestamp math rather than trusting a steadily-ticking counter, coming back to the tab after ten minutes away shows the genuinely correct elapsed or remaining time immediately, recalculated fresh against the real clock rather than having silently drifted or paused while the tab sat in the background unattended. That reliability was worth building the timing logic around timestamps from the very start rather than retrofitting it after noticing background tabs behaved differently.

Why there's no alarm sound yet

The countdown pulses visually when it hits zero, but there's no audio alert. That's a real gap for a timer — someone stepping away from the screen during a cooking timer or a work session won't see a visual pulse. I left it out of this first version because getting notification sound right means thinking about autoplay restrictions most browsers enforce around audio, and whether the tab even needs to be focused for a sound to play reliably. Those are solvable problems, just not ones I wanted to solve hastily in the same release as getting the core timing accuracy right, which mattered more to nail first.

A timer that's occasionally a little wrong is basically useless — the entire value proposition is trust in the number. So I'd rather ship without an alarm sound and have the timing itself be completely reliable, than ship with a satisfying chime attached to a clock that quietly drifts by a few seconds every time someone leaves the tab unattended for a while.

This one has a genuinely simple job — count up, or count down — and the entire post ended up being about the ways a naive implementation of "simple" quietly breaks under conditions a quick demo never surfaces: a backgrounded tab, an accidental reset, a laptop that briefly throttled its timers under load. Getting a timer boringly, reliably correct turned out to be a bigger job than the feature list makes it look.

Hello!