Status and SLOs
The current state
CoRelayer runs on devnet only; nothing is deployed on mainnet yet.
The state of each network is published where it is kept current, not written into this page:
/.well-known/corelayer.json names the
networks, their contract addresses and their API hosts; GET /v1/status carries the service state
and any open incident; and the changelog records every change.
What is built, and how it is tested
Each part is listed with what its tests cover, so that no page on this site has to be read as more than it is.
| Part | State |
|---|---|
| Smart contract | Built and tested. Reproducible build and explorer verification are not published yet. |
| Backend | The API, the signer, settlement and the other services are built and tested. They have been run end to end on a workstation against a mock chain — assign, relay, tracking to an executed state, billing, and a hard kill in mid-flight without losing or double-charging an intent. That is a test of the wiring, not a measurement: nothing about it is a latency or availability figure. |
| SDKs (TypeScript, Go, Rust, Python) | Built and tested. Not published to a registry yet. (SDK) |
| Dashboard, website, status site | Built, with unit, end-to-end and accessibility tests. |
| These docs | Built, with runnable examples tested against a stand-in API. |
Known gaps:
- The MCP server executes four of its twenty tools; the rest answer with a pointer to their REST route. (The MCP server)
- Usage proofs are served without their Merkle proof path yet. (Usage proofs)
- Plan-cap billing. Each API host serves an account from its own share of the account's cap. The allocator that grants those shares is now written and passes its tests against stand-ins for the database and the cache. Its tests against a real PostgreSQL and Valkey have not yet been seen passing, and no end-to-end run has yet billed a relay to a plan cap.
- Inclusion tracking has all three of its sources wired: the block feed, a per-intent tracker for anything the feed misses, and a sweep over our relayers' recent transactions. A test proves that an intent still reaches "executed" and "finalized" when the feed never delivers its block. None of it has run against a chain.
- Settlement of pay-as-you-go usage runs end to end in a test — the batch is built, signed and relayed by our own relayer — against stand-ins for the database and the chain. No settlement batch has yet been built against a real database or a chain.
Where status will live
| Status site | status.co-relayer.com — its own deployment, on infrastructure separate from the API, so that it survives an outage of the thing it reports on. |
| Feeds | /feed/status.json, /feed/incidents.json, /feed/telemetry.json — three files, because incidents and telemetry have different cache lifetimes. |
| From the API | GET /v1/status, GET /v1/incidents, GET /v1/incidents/{id} — the same data, public. |
| For your account | GET /v1/account/{erd}/outages — the outages that affected you, which is a different question from "was there an incident". |
A status page hosted on the same machines as the service it reports on is a status page that goes down when you need it. Hence the separation.
Each deployment of co-relayer.com also serves
/build-info.json: the environment, the chain and the
commit it was built from.
Relayer funding, without balances
Whether a shard can pay for your transaction is a status, not an amount. A watcher keeps every
active relayer above a funding floor, and a relayer leaves the assignable set before it falls below
what a transaction costs. The public view is one label per shard: floatPerShard in
GET /v1/status, with the status ok, low or critical. A shard with no relayer left to
assign answers NO_RELAYER_AVAILABLE, with Retry-After.
Exact hot-wallet balances are not published. They would be a shopping list for an attacker, and the label answers the only question a customer has.
What we publish, and what we refuse to publish
Availability and latency are published only once they have been measured over enough time to mean something. Until then there is no measured availability, no measured latency distribution and no basis for a service-level objective.
Publishing one anyway would mean inventing it. Wherever this documentation has to describe an intention it says "designed for"; where it would otherwise be guessing, it says nothing.
This is a deliberate policy, not an oversight, and it applies to the service level agreement too: there are no SLA percentages and no service credits at launch. They arrive when there is data to base them on — and when they do, the remedy is denominated in Relay Units and granted through a contract endpoint, not in a discretionary credit note.
What is measured
The instrumentation exists; figures are published once there is enough data behind them.
Per transaction
| Field | Interval |
|---|---|
acceptToCosignMs | Received → the relayer signature was released |
cosignToBroadcastMs | Signature → a gateway acknowledged it |
addedMs | Received → acknowledged |
inclusionMs | Received → the block that executed it |
finalityMs | Executed → final |
totalMs | Received → final |
roundsToInclusion | Inclusion expressed in chain rounds |
The first two are ours. Inclusion and finality are the network's. They are reported separately so that our own queueing cannot hide inside the chain's variance. (Latency)
Per account
GET /v1/usage/latency reports p50, p95 and p99 over your transactions. That is a fact about
what happened to you. It is not a forecast and it is not a commitment.
Service-wide
GET /v1/status carries the service state, a per-component breakdown and any open incident. A
witness host separate from the API publishes the status feeds, so the report does not depend on
the thing being reported on.
Incidents
| Declared | By the operators, with an id (inc_…) and a first update. |
| Published | Immediately, to the status feeds and to GET /v1/incidents. |
| Delivered | As an account notice and a webhook to affected accounts, not only as a page somebody has to remember to load. |
| Per account | GET /v1/account/{erd}/outages — the periods where your traffic was affected. |
Incidents have an id (inc_…) and a history, so an update is appended rather than replacing what
was said earlier. A status history that can be quietly rewritten is not a status history.
What "degraded" will mean
These are the conditions that will be reported, so they are worth knowing in advance:
| Condition | What you would see |
|---|---|
| A shard has no healthy relayer | NO_RELAYER_AVAILABLE on assignment, with Retry-After |
| The signer is unreachable or has fenced itself | SIGNER_UNAVAILABLE, SIGNER_FENCED — nothing was co-signed |
| Gateways are unreachable | UPSTREAM_UNAVAILABLE before the commit point |
| The platform admission budget binds | RATE_LIMITED with details.scope = "platform", and an incident |
| The exchange venue is paused | SWAP_VENUE_PAUSED on purchases; relaying is unaffected |
| Our contract is paused | CONTRACT_PAUSED on purchases |
Note the last two: a purchase problem is not a relay problem. Relaying an already-entitled account's transactions continues while the venue or the contract is unavailable.
The guarantee that does not depend on measurement
One property holds regardless of load, latency or incident:
An error from POST /v1/relay means nothing was sent. No error is returned after the relayer
signature exists. Whatever else is degraded, that boundary holds — and it is the property your
retry logic should be built on, because it is the one that is true even during an outage.
(Delivery guarantees)