hard What Is the Difference Between Wall‑Clock Time and Monotonic Time, and Why Is Clock Skew
Wall-clock time (system “real time”) is the machine’s current date/time of day, which can jump forward or backward when the clock is adjusted (by NTP sync, daylight savings, manual change, etc.), while monotonic time is a steadily increasing timer (often since boot) that never goes backwards.
Clock skew is the drift or offset between different clocks (for example, on different servers), which is hard to eliminate because each clock runs at a slightly different rate and network sync protocols can’t perfectly align them.
Wall-Clock Time (Real Time)
Wall-clock time (also called system time or real-time clock) represents actual calendar time.
It answers questions like “what time of day is it?” and is used for timestamps, scheduling tasks, and logging.
Because it reflects human time (UTC/local time), it can be adjusted by external events: for instance, a time-sync service (NTP) might set your clock forward a few seconds, or a user could manually change the system time.
Such adjustments mean the wall-clock can jump or even move backwards (e.g. after a backward NTP update).
-
Example: If your laptop sleeps and then resumes, the system clock may jump ahead by the sleep duration, but any timers based on wall-clock will reflect that jump.
-
Consequence: Using wall-clock to measure elapsed time is unreliable in such cases, since the elapsed calculation might become negative or incorrect if the clock was changed mid-measurement.
In practice, wall-clock is great for events tied to real time (e.g. “run this job at 6:00 PM”), but programs must handle the fact that the clock can be reset, adjusted for leap seconds, or synced with internet time.
Learn about Vector Clocks.
Monotonic Time
Monotonic time is a special clock that only measures elapsed time. It typically counts continuously from a fixed point (such as system startup) and always increases at a steady rate.
Because it isn’t linked to the real-world date, it cannot be changed or set by the user or NTP. It will never jump backwards or forward.
This makes it ideal for measuring durations, timeouts, or intervals.
-
Example: To time how long a function takes, you’d use monotonic time for both start and end. Even if the system clock changes during execution, the monotonic clock simply kept ticking, so the elapsed value is correct.
-
Use case: Monotonic clocks are used under the hood in many programming languages. For example, Linux’s
clock_gettime(CLOCK_MONOTONIC)and Python’stime.monotonic()provide this behavior. Unlike the wall-clock, you can’t interpret monotonic time as a date, it’s just a high-resolution counter.
Key Differences
Unlike wall-clock time, monotonic time is immune to manual or automatic adjustments.
Wall-clock can be synchronized across machines (so 6 PM here means 6 PM there), whereas each machine’s monotonic clock is independent (each starts from its own zero).
Crucially, when measuring elapsed time, monotonic timers guarantee a non-negative interval, while wall-clock measurements might even go negative if the clock is set back.
-
Use monotonic time for measuring durations, timeouts, or intervals (e.g. how long a query took).
-
Use wall-clock time for actual date/time stamps, scheduling, or logging real-world events.

Clock Skew and Synchronization
Clock skew refers to the differences or drift between clocks, typically in a distributed system with multiple machines.
Even if all clocks are initially synced, each hardware clock “ticks” at a slightly different rate, so over time their readings diverge.
The difference in rate is called skew, and the difference in current time is called offset.
For example, imagine two clocks that start in sync.
If one runs just a tiny bit faster, after a while it will show a later time than the other; that growing gap is clock skew.
Why Clock Skew is Hard
Eliminating clock skew is challenging because there is no perfect global clock and physical limitations introduce error.
Some key reasons:
-
Hardware Drift: Every physical clock (crystal oscillator) has slight manufacturing and environmental variations. Temperature changes or aging cause clocks to tick faster or slower. You can’t guarantee two clocks run at the exact same rate. Even a tiny drift accumulates large offsets quickly.
-
Network Delays: Synchronizing clocks (via protocols like NTP) requires exchanging messages. Variability in network latency (jitter) means you never know the exact one-way delay, so any correction has some uncertainty.
-
NTP Limits: NTP can typically sync system clocks to within a few milliseconds on a local network. That’s fine for most purposes, but not adequate if you need microsecond or nanosecond precision (e.g. some financial systems or real-time sensors). NTP corrects small offsets by slewing — deliberately running the clock slightly fast or slow, capped at 500 ppm (0.05%), i.e. at most ~0.5 ms of correction per elapsed second — so small corrections never jump the clock. But for offsets beyond the step threshold (128 ms by default in ntpd) it steps the clock: a single discontinuous jump, forwards or backwards, of whatever size closes the gap; beyond the panic threshold (~1000 s) ntpd refuses and exits. chrony behaves similarly but only steps when explicitly allowed (
makestep). The backward step is the case that breaks wall-clock timeouts and ID generators — which is exactly why durations must use the monotonic clock, and why Snowflake generators guard againstnow < last_seen_ts. -
Resets and Adjustments: As with wall-clock jumps, synchronization can overshoot or be delayed. If a clock is adjusted backwards (for example, an NTP step or leap second), logs and timeouts relying on that clock may behave incorrectly. Some systems avoid stepping the clock backwards (slewing slowly instead) precisely because backward jumps break assumptions.
Because of these factors, complete elimination of skew is impossible.
In distributed systems, this makes tasks like globally ordering events by timestamp difficult.
For example, if Server A’s clock is a second ahead of Server B’s, an event logged at 12:00:01 on A might actually have happened after an event at 12:00:02 on B, causing confusion.
In practice, systems either tolerate some skew (e.g. by including clock uncertainty in algorithms) or use logical clocks (Lamport timestamps, vector clocks) that avoid relying on synchronized physical time.
Summary
Wall-clock (real) time and monotonic time serve different needs.
Use monotonic timers for measuring elapsed time to avoid jump-induced errors.
Clock skew is the inevitable mismatch between clocks. It is hard because every clock drifts and network sync is imperfect.
Understanding the difference and the limits of synchronization helps developers choose the right clock and design robust, time-sensitive code.
Choosing a clock — and what to use when no physical clock is trustworthy
The wall-vs-monotonic split settles the single-node question; the harder, interview-defining question is what to order events by across machines, where skew makes any physical timestamp untrustworthy.
- Measuring a duration or a timeout: always monotonic, never wall-clock. A wall-clock jump (NTP step, DST, sleep/resume) can make an elapsed calculation negative or fire a timeout early — a wall-clock timeout is a latent bug, not a style choice.
- Stamping a real-world instant (a log line’s UTC time, a TTL’s absolute expiry, a
created_at): wall-clock is required — but treat the value as skewed by up to your cluster’s NTP bound (often a few ms, occasionally far more), never as exact.
Ordering across nodes — named alternatives and the crossover. Do not use raw wall-clock time to decide “who wrote last”: under skew, Last-Write-Wins can pick a causally-earlier write as the winner and silently drop the newer one.
- Lamport clocks give a total order consistent with causality but carry no wall-time meaning — use when you only need “a happened-before b”, not “when”.
- Vector clocks additionally detect concurrency, so you can surface a conflict instead of silently losing a write, at the cost of O(nodes) metadata — use when you must know two writes were concurrent.
- Hybrid Logical Clocks (HLC) pair a physical component with a logical counter, staying within a bounded distance of wall-clock while preserving causality. The crossover: prefer HLC over vector clocks when you want causal ordering plus a near-real timestamp and don’t want per-node vectors — and it needs no special hardware.
- Google TrueTime exposes an explicit uncertainty interval ε (GPS/atomic-clock backed); Spanner commit-waits ~2ε — it assigns the commit timestamp
s = TT.now().latestand then holds the commit untilTT.after(s)is true, roughly two uncertainty-bounds later — to guarantee external consistency. Use only when you have that hardware and need linearizable cross-region ordering — the cost is commit latency proportional to the clock uncertainty ε.
The failure that hides here: never let a lease expire by wall-clock alone to decide leadership — a skewed or GC-paused node can believe it still holds the lease and create a second primary. Pair the lease with a monotonically increasing fencing token the resource checks, so a stale leader’s write is rejected regardless of what its clock says.
🤖 Don't fully get this? Learn it with Claude
Stuck on What Is the Difference Between Wall‑Clock Time and Monotonic Time, and Why Is Clock Skew? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **What Is the Difference Between Wall‑Clock Time and Monotonic Time, and Why Is Clock Skew** (System Design). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **What Is the Difference Between Wall‑Clock Time and Monotonic Time, and Why Is Clock Skew** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **What Is the Difference Between Wall‑Clock Time and Monotonic Time, and Why Is Clock Skew**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **What Is the Difference Between Wall‑Clock Time and Monotonic Time, and Why Is Clock Skew**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.