Introduction

You hit send, and a packet races across the internet in milliseconds. Somewhere along the way it picks up a timestamp. That timestamp is only useful if the two computers involved — sender and receiver — agree on what time it is.

They almost certainly don't. Every crystal oscillator runs at a slightly different speed, so clocks drift from the moment they are set. Leave a computer alone for a day and its clock may be off by seconds; leave it for a year and the error compounds to minutes. Distributed systems that use stale timestamps get confused: databases log events in the wrong order, security certificates appear expired before they are, financial trades arrive seemingly before they were placed.

NTP — the Network Time Protocol, designed by David L. Mills and first published as RFC 958 in 1985 — is how the internet fixes this. It is a layered hierarchy of time servers (called strata) that broadcast corrections derived ultimately from atomic clocks, and a clever measurement technique that strips network jitter out of the answer. The result: your laptop's clock is usually within a few milliseconds of true time, even though every packet it sends takes a different path and arrives after a different delay.

Try It

The simulation below shows a local clock that drifts away from the true reference time and a simulated NTP server correcting it. Each NTP exchange sends a request, waits for the reply, measures the round-trip time, and uses half of it to estimate the one-way network delay — then adjusts the local clock by the computed offset.

<!-- {{c_layout_comment}} -->
<div class="panel" id="panel">
  <div class="clocks">
    <div class="clock-box">
      <div class="clock-label">{{label_reference}}</div>
      <div class="clock-display" id="ref-display">00:00:00.000</div>
      <div class="clock-sub">{{sub_reference}}</div>
    </div>
    <div class="clock-box local-box">
      <div class="clock-label">{{label_local}}</div>
      <div class="clock-display" id="local-display">00:00:00.000</div>
      <div class="clock-sub" id="offset-display">{{sub_offset_init}}</div>
    </div>
  </div>
  <div class="timeline" id="timeline" title="{{timeline_title}}">
    <canvas id="canvas" width="560" height="90"></canvas>
  </div>
  <div class="info-row">
    <span id="info-text" class="info-text">{{info_idle}}</span>
  </div>
  <div class="btns">
    <button id="btn-sync" type="button">{{btn_sync_once}}</button>
    <button id="btn-auto" type="button" class="ghost">{{btn_auto}}</button>
    <button id="btn-reset" type="button" class="ghost">{{btn_reset}}</button>
  </div>
</div>
/* {{c_base_styles}} */
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; color: #1d2733; background: transparent; }
.panel { padding: .8rem; }
.clocks { display: flex; gap: 1rem; margin-bottom: .7rem; }
.clock-box { flex: 1; background: #e8eef3; border: 1px solid #cdd9e3; border-radius: 10px;
             padding: .6rem .8rem; text-align: center; }
.local-box { background: #fff7e6; border-color: #f0c060; }
.clock-label { font-size: .72rem; font-weight: 700; text-transform: uppercase;
               letter-spacing: .06em; color: #556; margin-bottom: .25rem; }
.clock-display { font: 700 1.35rem ui-monospace, monospace; letter-spacing: .04em; }
.clock-sub { font-size: .72rem; color: #667; margin-top: .2rem; min-height: 1em; }
/* {{c_timeline_styles}} */
.timeline { border: 1px solid #cdd9e3; border-radius: 8px; overflow: hidden;
            background: #f5f8fb; cursor: default; margin-bottom: .5rem; }
canvas { display: block; width: 100%; }
/* {{c_info_styles}} */
.info-row { min-height: 1.6em; margin-bottom: .5rem; }
.info-text { font-size: .85rem; color: #334; }
.info-text.synced { color: #0a7d33; font-weight: 600; }
.info-text.bad { color: #c92f3c; font-weight: 600; }
/* {{c_button_styles}} */
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 13px system-ui; padding: .4rem .85rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
button.active { background: #0a7d33; border-color: #0a7d33; color: #fff; }
// Code not found

Notice that each correction brings the local clock closer but never perfectly on target — network jitter (random variation in delay) means each measurement is noisy. NTP solves this by averaging many samples and applying a filter that discards outliers. Press Sync once to do a single NTP exchange; press Auto-sync to keep synchronizing automatically and watch the clock converge.

The Real Complexity

NTP's core measurement uses four timestamps collected during a single round-trip:

  • T1T_1: the time the client sent the request (client clock)
  • T2T_2: the time the server received it (server clock)
  • T3T_3: the time the server sent the reply (server clock)
  • T4T_4: the time the client received the reply (client clock)

From these four numbers, NTP computes two quantities:

δ=(T4T1)(T3T2)\delta = (T_4 - T_1) - (T_3 - T_2)

This is the round-trip delay — the total time the packet spent in transit, with the server's own processing time T3T2T_3 - T_2 subtracted out.

θ=(T2T1)+(T3T4)2\theta = \frac{(T_2 - T_1) + (T_3 - T_4)}{2}

This is the clock offset — how far the client clock is behind (positive) or ahead (negative) of the server. If the network is symmetric (same delay in each direction), θ\theta is exact. Real networks are not perfectly symmetric, but the average is a good estimate.

NTP corrects the local clock by +θ+\theta. If the offset is small it applies the correction gradually (slewing) to avoid sudden jumps that could confuse software; if the offset is large it steps the clock immediately.

The stratum system adds depth: a stratum-1 server is disciplined directly by an atomic clock or GPS; a stratum-2 server synchronizes to stratum-1; your laptop is typically stratum-3 or stratum-4. Each hop adds a small amount of uncertainty, which is why precision drops as you move down the hierarchy.

Modern NTP implementations like chrony and ntpd maintain a statistical filter over many samples, discarding outliers and weighting recent measurements more heavily, achieving typical accuracy of 1–10 ms on the public internet and sub-microsecond accuracy on local networks using the hardware timestamping variant PTP (IEEE 1588).

Where It Matters

Accurate clocks are a hidden load-bearing wall of modern computing:

  • Distributed databases: systems like distributed shortest paths and consensus protocols use timestamps to order events. A clock skew of even a few hundred milliseconds can cause writes to appear in the wrong order, corrupting data.
  • TLS certificates: HTTPS certificates carry a notBefore and notAfter field. A client whose clock is wrong by more than the certificate's validity window will refuse a perfectly valid certificate — or accept an expired one.
  • Financial markets: high-frequency trading systems are legally required to stamp orders with synchronized time. Regulators demand timestamps accurate to 100 microseconds or better.
  • Log correlation: when an incident spans dozens of servers, piecing together what happened requires logs that agree on time. Without NTP, events on different machines cannot be reliably sequenced.
  • GPS and mobile networks: every base station and satellite must broadcast on a precise schedule. The GPS system itself provides the atomic time signal that NTP stratum-1 servers consume.

NTP is an invisible piece of infrastructure that almost every protocol above it depends on — TLS, OAuth tokens, database replication, blockchain timestamps, and more. Understanding it illuminates why distributed systems treat time as a first-class resource, not a free given.

Conclusion

NTP solves a surprisingly subtle problem: how do you set your clock accurately when the very network you use to ask for the time introduces unpredictable delays? The answer — measure the round-trip, assume symmetry, split the difference — turns four timestamps into a correction that is good to within a few milliseconds on the public internet and far better on local networks.

It is a beautiful example of using what you can measure (round-trip time) to infer what you cannot directly observe (one-way delay) — the same spirit behind many algorithms in distributed systems and network science. The next time your computer's clock is correct to within a heartbeat of true time, you know what quiet protocol made that possible.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/network-time-protocol/Content licensed under CC BY-NC 4.0.