Clocks and the order of events
Two clocks never agree exactly: let one place number the events, or carry the order inside the messages.
Predict first
Before you read: predict
A concert's ticket sales run on two app servers, app-1 and app-2, both synced by NTP. On Saturday app-1's clock ran 30 ms behind app-2's. When a fan refunds a seat, the server handling it writes the refund to the shared audit table, then tells the other server, which resells the seat 10 ms after the refund was written. app-1 has been up since 06:00 and app-2 since 13:00. On Saturday evening 4 seats were refunded and resold, 2 refunded on each server.
Sorted by which field does the audit table list every resale after its refund?
The 30-second version
Every machine's clock drifts, and a correction can set it back, so timestamps from two machines cannot say which of two close events came first. When order matters, let one place number the events, or carry the order in the messages: Lamport clocks respect cause and effect, vector clocks also show concurrency. Time durations with a monotonic clock.
Two clocks never agree exactly: let one place number the events, or carry the order inside the messages.
How it works
Step 1 of 15
In the kitchen
- each warden's watch, set from the radio pips each morning and gaining or losing a little all day → each node's clock drifting between syncs (steps 1–2)
Analogy: A bird observatory and its three ringing stations along a migration route
Wardens at three coastal stations catch, ring and release birds, and radio their catches to the observatory.
| At the observatory | In a system |
|---|---|
| each warden's watch, set from the radio pips each morning and gaining or losing a little all day | each node's clock drifting between syncs (steps 1–2) |
| a warden finds her watch fast at noon and puts it back, so every later catch reads earlier by what she took off | a clock set back (step 3) |
| the log keeper writes each station's radio report in the order the reports come in | a sequencer, in arrival order (steps 5–6) |
| a warden numbers each note higher than any number she has written or read | a Lamport clock (steps 8–9) |
| the stopwatch timing how long a bird stays in the bag | a monotonic clock for a duration (step 14) |
In real terms: a timestamp is one clock's reading; an order needs one numbering place, or numbers passed along with the messages.
Breaks down when: a warden can radio the others to agree the time before she writes, while a server learns another's clock only through a message that itself takes time.
Contrasting case: one database's transaction log: one writer numbers every change, so its order needs no clock at all.
Examples, run for real
4.1 ExamHall: an anti-cheat timeline
EXH-4730: ExamHall's review console sorted a candidate's anti-cheat events by each source's own clock: the proctor pod's events by the pod, the browser's by the candidate's laptop, which ran 130 s slow. A paste landed inside a proctor's pause, and the attempt was flagged. MR !5030 sorts the timeline by the number the ingest service gives each event as it arrives.
4.1 EXH-4730 own clocks (laptop 130 s slow) tab hidden 09:58:30 · attempt paused 10:00:00 · paste 10:00:20 · attempt resumed 10:02:00 · pastes inside a pause 1
4.1 MR !5030 ingest sequence #1 attempt paused · #2 tab hidden · #3 attempt resumed · #4 paste · pastes inside a pause 0
The paste came 30 s after the resume; the laptop's clock moved it into the pause (step 4). The ingest numbers are the order the server received the events, the same for every reviewer (steps 5–6).
4.2 Ticketing: two box offices' logical clocks
North sells C4, tells south, then sells C5. South sold D1 before the message came and prints block C's seat map after it.
4.2 Lamport north: sell C4 1 · send 2 · sell C5 3 | south: sell D1 1 · receive 3 · print block C 4
4.2 vectors north: sell C4 [1,0] · send [2,0] · sell C5 [3,0] | south: sell D1 [0,1] · receive [2,2] · print block C [2,3]
4.2 compare sell C4 [1,0] vs print block C [2,3]: before · sell C5 [3,0] vs print block C [2,3]: concurrent
South's receive jumps from 1 to 3 (step 9). Sell C5 has a lower Lamport number than the print, yet neither vector is at most the other: they were concurrent (steps 11, 13).
Try it
Answer first, then check. Nothing is saved.
Question 1 of 7
On this lesson's clock model, a box-office server gives each order an ID from its own clock, Date.now() in milliseconds, and the sales report lists orders by ID. Its last order before the change is taken at 20:00:01.000 by that clock. At once, NTP steps the clock back 300 ms. The next 4 orders come 100, 200, 250 and 350 ms later, by elapsed time.
How many of those 4 orders get a lower ID than the order taken at 20:00:01.000?
Question 2 of 7
Three ticketing services keep Lamport clocks, each starting at 0. holds records a hold, then sends it to billing. billing has already recorded 4 card checks; it receives the hold, then sends a paid message to tickets. tickets has already recorded 1 seat-map update; it receives the paid message, then records the ticket as issued.
What Lamport number does the ticket-issued event get?
Question 3 of 7
Seat B7's map has three replicas, Rome, Oslo and Lima, each keeping a vector clock [Rome, Oslo, Lima] that starts at [0, 0, 0]. In this order: Lima writes "B7 held for Ben", then sends Rome a message; Rome writes "B7 held for Ana", then sends Oslo a message; Oslo receives Rome's message, then writes "B7 sold to Ana"; Rome receives Lima's message, then writes "Ben's hold noted".
Which of the other three writes does a vector-clock check flag as concurrent with Ben's hold?
Question 4 of 7
ExamHall's proctor service and its browser-event service both stamp events with Lamport numbers. A teammate says a candidate's paste (number 12) happened before the proctor's warning (number 15), because 12 is lower. Write two or three sentences to the teammate: what a Lamport clock is for, in one sentence; why 12 and 15 do not settle the order here; and what would show whether the paste came before the warning.
What do you write?
Question 5 of 7
On this lesson's database model, the box office's sales table takes each row's id from a Postgres sequence. Every second a report job reads the sales whose id is above the highest id it has read so far, starting above 40. Sale A's transaction takes id 41 at 20:00:00.100, waits on a slow card check and commits at 20:00:01.400. Sale B's takes id 42 at 20:00:00.300 and commits at 20:00:00.500. The job runs at 20:00:01.000 and at 20:00:02.000.
Which sales does the report ever read?
Question 6 of 7
On this lesson's clock model, two box-office servers sync with NTP every 10 minutes, and right after each sync both show the same time. Between syncs, server A's clock gains 2.4 ms a minute and server B's loses 3.6 ms a minute. Just before a sync, 10 minutes after the last one, five pairs of seat holds come in: in each pair a hold lands on A, then another on B, 10, 25, 45, 70 and 90 ms later.
In how many of the five pairs does A's hold also carry the earlier timestamp?
Question 7 of 7
On this lesson's clock model, a booking API's handler reads Date.now() and performance.now() when a request starts and again when it ends, and logs both differences. One booking takes 80 ms; 30 ms into it, NTP steps the server's clock forward by 1,000 ms.
Which pair does the log line show, wall clock first?
Go deeper
Pro tip
- Keep an order next to every timestamp you sort by. Give each event a number from one sequence (or a Lamport or vector stamp where there is no single place), keep the timestamp for display, and time durations inside one process. When: designing an audit log, an event timeline or a latency metric (steps 5, 10, 14). Verify.
Sources
- Leslie Lamport, Time, Clocks, and the Ordering of Events in a Distributed System, CACM 1978 (named in the row): the PDF at lamport.azurewebsites.net answered 200 on 2026-10-17, but it is a scanned image (CCITT fax pages, no text layer), so no passage of the paper could be saved; it keys nothing. Lamport's own commentary on his publications page: https://lamport.azurewebsites.net/pubs/pubs.html ·
lamport-pubs.txt. "There is only a partial order in which an event e1 precedes an event e2 iff e1 can causally affect e2"; "the use of timestamps to provide a total ordering of events that was consistent with the causal order". Supports steps 8–11. Valid as of 2026-10-17. - Node.js docs, Performance measurement APIs (
perf_hooks): https://nodejs.org/api/perf_hooks.html ·node-perf-hooks.txt. Named in the row.performance.now()"Returns the current high resolution millisecond timestamp, where 0 represents the start of the current node process." Supports steps 14–15. Valid as of 2026-10-17. - Node.js docs, Process (
process.hrtime): https://nodejs.org/api/process.html ·node-process.txt. "These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift." Supports step 14. Valid as of 2026-10-17. - W3C, High Resolution Time (Level 3), a standard: https://www.w3.org/TR/hr-time-3/ ·
w3c-hr-time.txt. "its wall clock sometimes needs to be adjusted, which means the unsafe current time can decrease, making it unreliable for performance measurement or recording the orders of events."; "The monotonic clock only exists within a single execution of the user agent"; "it can’t be used to compare events that might happen in different executions." Supports steps 3, 14–15. Valid as of 2026-10-17. - PostgreSQL 17 and 18 documentation, 9.17 Sequence Manipulation Functions: https://www.postgresql.org/docs/17/functions-sequence.html and https://www.postgresql.org/docs/18/functions-sequence.html ·
postgresql-17-sequence-functions.txt,postgresql-18-sequence-functions.txt. Not named in the row; a vendor's own documentation, cited for teaching only. Both versions: "To avoid blocking concurrent transactions that obtain numbers from the same sequence, the value obtained by nextval is not reclaimed for re-use if the calling transaction later aborts." Supports step 7: a number is taken when asked, outside the transaction's fate. Valid as of 2026-10-17.
Related lessons
Checked against the tools and docs as of 2026-10-17.