Skip to main content

Edge liveness

Two separate things get called "is the Edge up", and conflating them wastes time during an incident.

Liveness is whether an Edge session is heartbeating. Account-level.

Readiness is whether a chain can have addresses generated for it. Per chain, per account, and it can be red while the Edge is perfectly healthy.

Readiness, per chain

Every account has one readiness row per chain. The default state is red.

IndicatorStateConditionAddress generation
🔴 Rednot_readyNo extended public key registered — or for Solana and Stellar, no poolBlocked
🟢 GreenreadyActive key registered; a pooled chain's pool above thresholdAllowed
🟡 AmberquarantinedRotation detected, awaiting owner approvalBlocked
🟠 Orangepool_lowPooled chains only — Solana or Stellar below 20%Allowed, replenish requested
curl -s $CLOUD/v1/edge/readiness -H "Authorization: Bearer $TOKEN" | jq

In the console: Settings → Edge readiness.

🟢 Bitcoin zpub6rFR7…4Q2A v1 registered 15 Aug
🟢 Ethereum xpub6CUGR…nZSQ v1 registered 15 Aug
🟢 BNB Chain xpub6CUGR…nZSQ v1 registered 15 Aug
🟢 Polygon xpub6CUGR…nZSQ v1 registered 15 Aug
🟢 TRON xpub6D4BD…cP2G v1 registered 15 Aug
🟢 XRP Ledger xpub6Bosf…nifz v1 registered 15 Aug
🟢 Solana pool 842/1000 v1 replenish at 200
🟢 Stellar pool 936/1000 v1 replenish at 200

All chains ready. Edge synced 15 Aug 2026, 09:12 UTC.

Ethereum, BSC, Polygon, Avalanche and Base show the same extended public key. That is correct — they share coin type 60'. See HD derivation.

Only the first eight and last four characters of a key are ever rendered.

Before any Edge has connected, every row is red with "Start your Edge container to register this chain." That is the expected state of a new account, not a fault.

Amber is never routine

quarantined means a different mnemonic is mounted against your account. Address generation is blocked on that chain until an owner approves the rotation with a fresh TOTP code.

Do not approve it to clear the alert. Find out why the identity changed first. See Identity rotation.

Liveness

The Edge heartbeats every 30 seconds — over the gRPC stream if it holds one, falling back to POST /v1/edge/heartbeat if the stream is down, which also serves as the reconnect signal.

StateMeaning
liveHeartbeating
staleA heartbeat is overdue but within tolerance
downBeyond the threshold. edge_offline has fired
never_connectedNo Edge has ever synced for this account and environment

The console shows this as a status dot in the top bar of every screen, polled every fifteen seconds so every screen agrees. Two webhook events carry it too:

edge_offline down beyond the threshold. Account-level, not a chain event
edge_online recovered

Subscribe to both. They are how your own alerting learns about it without polling.

What an offline Edge breaks — and what it does not

This is the table to have open during an incident.

OperationEdge offline
Deposit detection✅ Unaffected. Entirely Cloud-side
Confirmation tracking✅ Unaffected
Webhook generation✅ Unaffected
Webhook delivery to youLate, not lost. Queued and delivered on reconnect
Balance reads✅ Unaffected via Cloud
Address generation, the seven secp256k1 chains✅ Unaffected. Cloud derives from stored keys
Address generation, Solana and Stellar⚠️ Works while each pool lasts, then 423 EDGE_OFFLINE
Withdrawals423 EDGE_OFFLINE. Nothing can be signed

The headline: money still arrives and is still tracked. An offline Edge is a delivery delay and a signing outage, not a monitoring gap. That is the single most useful thing to know at 3am, and it is why the Edge is allowed to be a single container.

423 EDGE_NO_LEADER is the variant where replicas are live but none holds the lease — usually a partition. See High availability.

Sessions and split-brain

Settings → Edge sessions lists every active session: role (leader or follower), version, liveness, lease epoch, outbox mode, last heartbeat and pod hint. Ended sessions are reaped after an hour, so the list reflects the running fleet rather than an accumulating history.

curl -s $CLOUD/v1/edge/sessions -H "Authorization: Bearer $TOKEN" \
| jq '.data[] | { podHint, role, leaseEpoch, liveness, outboxDepth, edgeVersion }'

The lease epoch is the column that matters, and it is surfaced for one reason: during a split-brain every per-session health indicator is green — each replica genuinely is healthy — and the epoch is the only thing that reveals two replicas disagreeing about who leads.

Expect exactly one leader, and every session reporting the same epoch. Two leaders, or a follower whose epoch exceeds the leader's, is a genuine incident.

Cloud fences this: a frame carrying an epoch below the current one is refused with 409 LEASE_EPOCH_STALE and the stream is closed. So a stale leader cannot act — but you still want to know it happened, because it means your network partitioned.

Recovering

# Is it running, and what does it say about itself?
docker ps --filter name=chainos-edge
curl -s http://localhost:8787/v1/edge/health
curl -s http://localhost:8787/v1/edge/lease
curl -s http://localhost:8787/v1/edge/outbox

The Edge's status page at http://localhost:8787/ works before any sync — which is exactly when the console can tell you nothing, because Cloud has no keys for you yet.

After a restart:

  • The log reads resumed with Cloud, not synced with Cloud. Enrolment is a one-off.
  • The outbox drains in order. A large depth takes time; that is correct behaviour, not a hang.
  • Readiness returns to green without an operator doing anything, provided the same mnemonic is mounted.

Force a re-registration only if you have a reason:

curl -X POST http://localhost:8787/v1/edge/resync -H "X-API-Key: $CHAINOS_EDGE_KEY"

409 ALREADY_ENROLLED in response is Cloud declining to re-register something unchanged. That is not an error — it is the gate that makes an Edge re-syncing in a loop visible rather than merely expensive.

Troubleshooting has the failure-by-failure sequence.