Concepts & human language

Wall clock vs monotonic

Which clock to use — one can jump backward, the other only ever moves forward.

Every operating system exposes at least two kinds of clock, and using the wrong one for the job is a common source of subtle bugs.

The wall clock (also called “system time” or “real time”) reflects the current time-of-day as understood by the operating system. It can — and does — jump forward or backward: NTP corrections, manual admin changes, virtual machine migrations, and DST transitions can all shift it. In Python this is time.time() or datetime.now(); in JavaScript it is Date.now().

The monotonic clock is a counter guaranteed to only ever increase. It does not correspond to any calendar time; it typically measures seconds (or nanoseconds) since some arbitrary OS-specific epoch. Because it never jumps backward, it is the correct tool for measuring elapsed time, timeouts, and benchmarks. In Python: time.monotonic(). In JavaScript: performance.now(). (Go folds a monotonic reading into the wall-clock value returned by time.Now(), so subtracting two such values yields a correct elapsed duration automatically.)

Use the right clock for the job

  • Displaying or recording when something happened → wall clock.
  • Measuring how long something took → monotonic clock.

Pitfall: Measuring the duration of an operation with wall-clock timestamps (end_time - start_time using time.time() in Python or Date.now() in JS). If an NTP correction fires between the two readings, the measured duration will be wrong — possibly negative. Use time.monotonic() or performance.now() instead.

Go deeper: clock sources, NTP, and virtual machines

Modern systems expose several clock sources at varying precision and cost:

  • CLOCK_REALTIME (POSIX): the wall clock. Settable; can jump.
  • CLOCK_MONOTONIC (POSIX): never decreases; may pause when the system sleeps on some OSes.
  • CLOCK_BOOTTIME (Linux): like CLOCK_MONOTONIC but includes time the system was suspended.
  • CLOCK_TAI (Linux): International Atomic Time — like UTC but without leap second adjustments.

In virtualised environments, the wall clock is especially unreliable: when a VM is paused and resumed, the guest’s wall clock may be frozen during the pause, causing a sudden forward jump when it catches up. This is a common source of “expired” TLS certificates and missed cron jobs inside containers.

JavaScript’s performance.now() is guaranteed by the spec to be monotonic and is not affected by changes to the system clock. However, browsers deliberately reduce its resolution (to ~1 ms or coarser) as a Spectre mitigation.

For how duration arithmetic interacts with calendar units, see Durations & intervals.


← Back to all topics