Is my clock right?

Skip the details — take me to the bottom line ↓

This site keeps making the same uncomfortable observation from different directions. A receiver with the antenna position wrong reports the wrong time with complete confidence. A traceability claim needs a monitoring record showing you stayed inside your budget, not merely that you configured it once correctly. Timing failures are frequently quiet.

Which leaves an obvious question the rest of the site keeps not answering: how would you know?

Why one clock cannot tell you

Start with why this is hard, because it is not a matter of better firmware.

A clock’s error is the difference between what it says and what is true, and one clock has access to exactly one of those. Everything it can measure — its own oscillator, its own PPS, its own solution residuals — is measured in its own frame, and a constant error moves that whole frame together. You cannot detect a silent error from inside the thing that has it.

That is not a limitation anyone has failed to engineer around. It is the shape of the problem.

Which failures are loud, and which are not

Worth separating, because half the anxiety here is misplaced and the other half is not nearly anxious enough.

Loud — the antenna cable is cut, the receiver loses lock, the satellite count goes to zero, the PPS stops. Every one of these announces itself, and every monitoring system already catches them.

Quiet — the antenna moved a meter, a cable was replaced with a different length, a firmware update changed a delay, the configured position was wrong from the start, the room warmed up. Every one of these produces a clock that is confidently, steadily, invisibly wrong.

The loud ones get all the alerting. The quiet ones cause the incidents you find out about from somebody else.

The only detector is a second clock

So you need something outside the frame. Two clocks that ought to agree, and do not, are telling you something neither of them could tell you alone.

That much is standard resilience reasoning and most people arrive at it unaided. The part that is not standard — and the part worth the rest of this page — is how little independence you actually have. A completely independent second clock is much harder to come by than it sounds. Two clocks in the same building share a room, a power feed, a network, a configuration, often an antenna, and always the person who set them up.

So take an inventory. Write down what your two clocks share and where they are genuinely independent — and keep that list in mind every time you read one against the other. The boundary between the shared column and the independent one is exactly what decides what you can and cannot learn by comparing them.

Where that boundary falls, and what it costs you

Here is the counterintuitive bit, and it runs the opposite way to the instinct.

Put two receivers on one antenna through a splitter and you have deliberately made them share almost every systematic there is: the same antenna position, the same feedline delay, the same sky, the same multipath, the same weather. A skeptic would say you have ruined the comparison.

You have done the opposite. Because everything else is common, any disagreement that appears must be the receivers. The comparison is exquisitely sensitive to exactly one class of fault, and blind to the rest. In our lab, two receivers sharing an antenna produce independent position solutions that ought to land on the same point to within millimeters; when they do not, the problem is in a receiver, and no single-receiver self-test could have told us that.

Now give the second receiver its own antenna on the other side of the roof. You have given up that sensitivity — the two now disagree a little for a dozen innocent reasons — and bought something you could not have otherwise: the comparison can now see an antenna problem.

Here is that inventory for the arrangements you are most likely to have. Read it as two columns of one list: what is independent, and therefore what shows up.

your second clock catches cannot see
second receiver, same antenna receiver faults, firmware changes, configuration drift — at millimetre sensitivity anything about the antenna, feedline, position or sky
second receiver, own antenna antenna moved, feedline changed, local multipath anything common to the site
different constellation one operator’s bad day, one constellation’s prediction error a receiver fault affecting both
a national laboratory, by time transfer everything local, including the whole site little — this is the widest net
a second GNSS receiver on the same signal almost nothing a spoofer would trip a spoofed signal both are happily tracking

None of that is module-only. A second GPS network clock on its own antenna gives you the second row; two of them fed from one antenna through a splitter gives you the first; and a network clock with a PPS input will compare against another clock directly, which is the cheapest version of this there is. The arrangement is the design decision, not the class of hardware.

Read down the “cannot see” column and the design rule writes itself: choose what your second clock shares, on purpose, according to what you are trying to catch. A backup you never compare against inherits exactly the same silence as the primary — and a comparison whose two halves share the fault you fear is worse, because it produces confident agreement.

Comparison detects divergence, not error

The sharp limit, and it is the same argument as agreement is not accuracy, pointed at monitoring instead of at requirements.

Two clocks that drift together tell you nothing. If both receivers share an uncompensated feedline delay, they will agree perfectly and both be wrong. If both track a spoofed constellation, they will agree beautifully.

Agreement is evidence of nothing on its own. It is only informative in proportion to how independent the two clocks are — which is why the table above is the whole design, and why “we have two of them” is not an answer to the question.

Second clocks you can have this week

Four that cost little and are not widely used.

A different constellation. Free, already in your receiver, and it catches an entire class of failure — one operator having a bad day. BIPM’s own scorecard shows GLONASS running an order of magnitude worse than the others for over a year, which is exactly the kind of thing a single-constellation installation would never notice.

A link to a national laboratory. The observations are public and free. You will not get a defensible absolute offset without calibration — but you do not need one to monitor. A step in the link is a step in your hardware. If your offset jumps 40 ns one Tuesday, something in your installation changed on Tuesday, and it does not matter that you cannot say what the offset should have been.

Every inbound message stream that carries a timestamp. Somebody else’s clock, already arriving at your door. This one is the best of them, so it gets a section of its own below.

The clock’s own confidence, published rather than swallowed. PTP carries a clockClass field precisely so a grandmaster can announce my reference is gone and my confidence is degrading. A system that knows it is in holdover and does not say so has solved the easy half of the problem.

The free second clock already arriving at your door

If you are already timestamping a reasonably fast message stream that carries somebody else’s timestamps — market data, an exchange feed, a partner’s API, logs from another company — you already have the raw data a clock comparison needs. What is missing is only parsing their timestamp and setting up the analysis. It works best on streams carrying at least one timestamp per second.

Subtract their timestamp from yours and look at the shape. The difference has two parts. There is a physical minimum you can never beat: speed of light over the distance, serialization delay, the time it takes a CPU to do the work with zero stalls. And there is a variable delay stacked on top of it. The long list of sources sorts into two: contention and inefficiency. A message may be delayed contending for a shared CPU core or a switch port. Or it may be delayed by the bad luck of hitting a cold cache — missing out on a mechanism that would have made it faster. Plot the distribution and the variable part is typically log-normal, piled up against that hard physical floor.

The variable part is noise for this purpose. The floor is the signal.

How to run it

  1. Pick an interval that gives you at least several thousand samples of your timestamp minus theirs. You need enough in each interval to get a clean reading of the floor in the next step.
  2. Log the minimum timestamp difference from each interval, all day. That minimum is the luckiest message — the one that met no contention and hit nothing cold, so the variable delay got out of the way entirely. What is left is the floor plus the clock difference and nothing else.
  3. Expect it to be able to go negative. If their clock or yours is off, the floor moves below zero, and a tool that assumes latency cannot be negative will hide exactly the case you are hunting.
  4. Log the maximum too, while you are there. It costs nothing and it tells you your worst-case latency on that stream — a second useful number from the same pass. If the minimum is the luckiest message, the maximum is the unluckiest.
  5. Do it for every stream you receive, and deliberately choose ones that have nothing to do with each other: different companies, different industries, different geographies.

Separating the floor from your clock

The minima are not yet a clock measurement. Each one is the physical minimum plus your clock minus theirs, added together, and on day one you have no way to say which part is which.

Watching solves it. Run it for days, then take the average of the minima and call that the physical minimum. The floor is a property of distance and hardware, so it holds still while a clock difference does not; average over long enough and what survives is the constant. Subtract that baseline from each new interval minimum as it arrives and you have what you were after all along: your clock minus theirs, in nanoseconds, updating all day, on a stream you were already receiving.

Now you have something to alarm on. Not a round number somebody liked — the historical spread of that particular stream’s differences, learned from the same data. An excursion outside the range this stream has shown you for a week is worth a page; the same 50 ns on a different stream might be perfectly ordinary. Every stream calibrates its own threshold.

What the baseline quietly absorbs

Averaging the minima cannot tell a constant path delay from a constant clock offset — so if you were 200 ns off on day one, that 200 ns is now baked into your baseline and reads as zero forever after.

This is divergence, not error, again: the technique is exquisite at detecting change and blind to a standing offset. For the absolute number you need a calibrated path. For catching the day something moved, this is the best instrument you own.

The floor can also move for honest reasons — a rerouted circuit, a new switch, a NIC replaced. That is the same common-mode test read backwards: a step on one stream is a network change, a step on all of them is your clock.

And here is what makes it the best second clock you have

Those counterparties share almost nothing. Different clocks, different vendors, different networks, different countries, different reasons to be wrong.

So if all your minimum differences move in the same direction at the same moment, it is not a coincidence and it is not them. It is you. Nothing else could move every unrelated stream at once.

That is the independence argument from the table above, taken to its limit — and unlike every other row, it needs no hardware, no subscription and no installation. The data is already coming in.

You may be surprised at what you see.

Keep a few weeks of it. The difference series is small, cheap to store, and it is the record you will want the day somebody asks what your clock was doing last Tuesday. Forensic questions arrive without warning and cannot be answered retrospectively from data nobody kept — which is the same argument the monitoring record rests on, arriving from a completely different direction.

Make something complain

A comparison nobody reads is not monitoring. Three properties separate the real thing from a dashboard:

  1. It alarms on divergence, not on absence. “The GNSS receiver is up” is the loud failure you already catch. “The two clocks moved 30 ns apart” is the quiet one.
  2. The threshold is your error budget, not a round number somebody liked. If you have not written the budget down, the alarm level is a guess and will be tuned until it stops firing.
  3. It keeps the record. This is the part that converts monitoring into traceability — the requirement is a record showing you stayed inside the budget over the period being claimed, and that record cannot be reconstructed later. It exists only if you were writing it down at the time.

That third point is the one that catches people at audit. Everything else on this page is engineering; that one is the difference between having been right and being able to show it.

The short version

  • Nothing inside one clock can detect a constant error. Stop looking for a self-test that would.
  • Get a second clock, and inventory what it shares with the first, because that boundary decides what the comparison can see.
  • Agreement proves nothing in proportion to what the two clocks have in common.
  • Alarm on divergence against your written budget, and keep the record — the record is the part you cannot backfill.

Where to go next