Compare server clocks without claiming synchronization
Compare the local clock with an external HTTP receipt to surface disagreement. SpyderGoat does not discipline or synchronize the local clock.
Calculate an estimated offset
estimated_offset_ms = server_utc_ms - ((client_send_wall_ms + client_receive_wall_ms) / 2)
round_trip_ms = client_receive_monotonic_ms - client_send_monotonic_ms
The midpoint calculation assumes a stable client wall clock during the request and approximately symmetric network and processing delay. The example maps monotonic elapsed time onto the send wall-clock reading so an adjustable wall clock is not used to measure RTT.
This is an estimated offset and observed disagreement, not a correction or direct measurement of drift. The response does not expose one-way delay or Worker processing duration.
Interpret the runtime result
A positive estimatedOffsetMs means the receipt UTC was later than the calculated local midpoint. A negative value means it was earlier.
Either sign combines possible clock disagreement with asymmetric latency, Worker processing, response transfer, local process scheduling, and the midpoint assumptions. Asymmetric request and response paths make the estimate uncertain.
One sample cannot determine which clock is wrong. It also cannot distinguish persistent disagreement from transient network or scheduling delay.
Choose application-specific thresholds
There is no universal safe threshold. Choose an application-specific threshold from the system requirement and keep each estimated offset beside its raw RTT or round-trip time.
Repeated samples can reveal consistency. Lower-RTT observations may reduce network noise, but do not prove either clock accurate; retain repeated samples and raw RTT values rather than hiding them behind an average.
The current free KV-conditional limit does not permit rapid sampling: one successful unauthenticated GET per CF-Connecting-IP value per 30 minutes is shared across /mjd and /jd when the binding is configured. Respect 429 and Retry-After.
Compare, do not synchronize
NTP is a clock-synchronization protocol; SpyderGoat is an HTTP comparison point. This script reports a comparison. It does not set the local clock, discipline frequency, build a clock model, or implement an NTP client.
SpyderGoat publishes no accuracy SLA, and no accuracy SLA exists for either side merely because this comparison was run. It also publishes no uptime, latency, or maximum-error guarantee.
Examples
Working JavaScript comparison
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5000);
const clientSendWallMs = Date.now();
const clientSendMonotonicMs = performance.now();
try {
const response = await fetch("https://spydergoat.com/mjd", {
headers: { Accept: "application/json" },
signal: controller.signal,
});
const clientReceiveMonotonicMs = performance.now();
const roundTripMs = clientReceiveMonotonicMs - clientSendMonotonicMs;
// Wall-clock mapping: assume the local wall clock stays stable during this RTT.
const clientReceiveWallMs = clientSendWallMs + roundTripMs;
if (response.status === 429) {
throw new Error("SpyderGoat rate limited; Retry-After=" + response.headers.get("Retry-After"));
}
if (!response.ok) {
throw new Error("SpyderGoat HTTP " + response.status);
}
const receipt = await response.json();
const serverUtcMs = Date.parse(receipt?.utc);
if (
receipt === null ||
typeof receipt !== "object" ||
!Number.isFinite(receipt.mjd) ||
typeof receipt.utc !== "string" ||
!Number.isFinite(serverUtcMs) ||
new Date(serverUtcMs).toISOString() !== receipt.utc ||
!Number.isSafeInteger(receipt.unix) ||
receipt.source !== "server"
) {
throw new Error("Unexpected SpyderGoat response");
}
const localMidpointMs = (clientSendWallMs + clientReceiveWallMs) / 2;
console.log({
receiptUtc: receipt.utc,
localMidpointUtc: new Date(localMidpointMs).toISOString(),
estimatedOffsetMs: serverUtcMs - localMidpointMs,
roundTripMs,
});
} finally {
clearTimeout(timer);
}Expected runtime output shape
All values shown as placeholders must come from the executed request; no numerical offset is fabricated.
{
"receiptUtc": "<ISO string measured at runtime>",
"localMidpointUtc": "<ISO string measured at runtime>",
"estimatedOffsetMs": "<number measured at runtime>",
"roundTripMs": "<non-negative number measured at runtime>"
}Limits and non-guarantees
- What this receipt does not guarantee: SpyderGoat returns a server-derived HTTP time receipt derived from the Cloudflare Worker runtime clock. The Worker clock is read during response construction. It is an unsigned HTTP receipt, not NTP, an atomic-clock feed, a signed timestamp, or an RFC 3161 authority or timestamp token. It does not synchronize or discipline your clock, and it does not prove when an external event occurred. Displayed precision is not an accuracy guarantee. HTTP and network latency affect comparisons. SpyderGoat publishes no uptime or accuracy SLA.
- Midpoint estimates cannot remove unknown asymmetry, Worker processing time, response transfer, or local scheduling effects.
Runtime provenance
This page describes current behavior defined by buildTimeResponse, checkFreeRateLimit, and request routing in src/api/worker.js, with public API behavior asserted in test/worker.test.js. The value source: "server" is a literal marker added by the Worker. It is not a signature, authentication, origin proof, or clock-quality attestation.