Skip to main content

What the latency numbers measure

CoRelayer will publish latency figures in four places: on every intent, in each account's latency report, per shard in the network document, and on the status site. None of them exists yet — nothing has run in production, so there is nothing measured to show. This page fixes what each figure means, so that when numbers appear they can be read precisely and checked.

No targets on this page

It describes measurements, not objectives. An objective is published only once there is enough measured data behind it, and it is then shown next to its measured value. (Status and SLOs)

Five timestamps​

Every relayed transaction carries up to five timestamps, each in Unix milliseconds:

TimestampThe momentWhose clock
receivedAtMsThe API received your POST /v1/relay.CoRelayer's
cosignedAtMsThe signer released the relayer signature — the commit point.CoRelayer's
broadcastAtMsThe first gateway acknowledged our hash.CoRelayer's
executedBlockTsMsThe timestamp of the block that executed the transaction.The chain's
finalizedAtMsThat block became final.CoRelayer's observation of the chain

A timestamp that is genuinely unknown is null, never estimated. That happens for rows restored by orphan recovery after a crash, where the original receive time was never journaled.

CoRelayer's hosts are designed to keep their clocks synchronised against several time sources, to report themselves not ready when the offset grows too large, and to stop minting leases on an unsynchronised clock. That is what bounds the error in the figures below that subtract a chain timestamp from one of ours.

Seven derived figures​

Every figure is a difference of two of those timestamps, or a count derived from one:

FigureFormulaWhat it isolates
acceptToCosignMscosignedAtMs − receivedAtMsOur validation, reservation and signing.
cosignToBroadcastMsbroadcastAtMs − cosignedAtMsOur path to the network.
addedMsbroadcastAtMs − receivedAtMsEverything CoRelayer adds before the network has the transaction.
inclusionMsexecutedBlockTsMs − receivedAtMsFrom your request to execution — ours plus the network's round.
finalityMsfinalizedAtMs − executedBlockTsMsThe network's finality.
totalMsfinalizedAtMs − receivedAtMsEnd to end.
roundsToInclusionceil(inclusionMs / roundDurationMs)Inclusion counted in chain rounds — roundDurationMs is in GET /v1/network.

Plus crossShard: whether the transaction left the sender's shard, because a cross-shard effect takes a further step and belongs in a different distribution.

The split is the point. The first three figures are the part CoRelayer controls; inclusion and finality are the network's. A service that published only totalMs could hide its own queueing inside the chain's variance, and a round of 600 ms makes that variance large next to anything a relayer adds.

Where each figure appears​

On one intent​

GET /v1/relay/{id} and GET /v1/intents/{sender}/{nonce} return the timestamps and a latency object with the derived figures. So do the per-intent event stream and the Transactions screen of the dashboard. This is a record of what happened to one transaction.

For your account​

GET /v1/usage/latency reports percentiles over your transactions:

Parameter or member
window1h, 24h, 7d or 30d.
groupByshard, relayer, sender, or gateway — the gateway that acknowledged first.
groups[].added, groups[].inclusionp50Ms, p95Ms, p99Ms of addedMs and inclusionMs.
groups[].binsA server-side histogram of inclusionMs, each bin a count up to leMs; the last bin is the overflow.
groups[].samplesAt most 48 sampled transactions per group, for a strip plot, each with its hash.
sloTargetInclusionP99Msnull until an objective is published.

It is private — native-auth or a read key — because it is our measurement of you. The percentiles are computed on the server from rollups, not from the samples.

Per shard, in the network document​

GET /v1/network carries shards[]: for each shard, addedP50Ms, addedP99Ms, inclusionP50Ms, inclusionP95Ms, inclusionP99Ms, the number of samples and the windowMs they cover, the time of the last block, whether the shard is stalled, and relays24h.

On the status site​

GET /v1/status, and the status site's own /feed/telemetry.json, carry:

MemberMeaning
latency30d[]Per shard, the same percentiles over the last 30 days — or since measuredFromMs, while the service is younger than that.
availabilityDaily90[]One entry per UTC day: the measured availabilityPct and the number of published incidents that touched the day. null for a day without data.
availability30dThe measured share of valid relay requests that got a BROADCAST or a correct 4xx. null until 30 days of data exist.
relays24hCustomer relays in the last 24 hours.

The status site is a separate deployment that reads three feed files — status, incidents, telemetry — so it keeps working when the API does not.

What is excluded​

  • Synthetic probes. A monitoring host sends a small number of real relayed transactions of its own, from dedicated low-value sender wallets, to check the whole path end to end. Those rows are marked internal and are excluded from every public figure — relays24h, latency30d, the shard percentiles and the marketing site.
  • Rejected requests. A request that never reached the commit point has no cosignedAtMs and contributes nothing to latency. It counts in availability only as what it was: a correct 4xx or not.
  • Unknown timestamps. A null stays out of the percentile it would have fed; it is never replaced by an estimate.

Reading a percentile correctly​

A percentile over your own transactions is a fact about what happened to you, in a window, with a sample size next to it. It is not a forecast and it is not a promise. When the sample is small the number is noisy, which is why every figure is published with the count or window it came from.