A chain node fell behind — RPC and confirmation diagnosis
Prove whether a blockchain endpoint is dead, wrong or merely stale using the requirements and diagnostics screen, and know what stops in what order when it is.
On-chain deposits stop confirming and on-chain withdrawals stop broadcasting for one chain while everything else on the platform behaves perfectly. Nothing on the dashboard says "the Ethereum node is behind", because from the platform's point of view the node answered — it just answered with yesterday's block.
The product has a screen built for exactly this. Extensions → Ecosystem →
Blockchains → Requirements (/admin/ecosystem/blockchain) is a per-chain
configuration report with a live probe attached to each chain, and it is where
this runbook starts and mostly ends.
Every check on that page asks "does this endpoint answer, and does it claim the right chain id". None of them compares the block height to anything. A node frozen fifty thousand blocks in the past passes the RPC check, passes the capability check, and reports Ready.
The block height is printed in the check's detail line. Comparing it to a public explorer is a manual step, and it is the whole diagnosis.
If payouts have stopped on every chain at once, this is the wrong runbook —
check the scheduler console first, because a stopped cron
process produces the same symptom everywhere simultaneously. If only token
withdrawals fail on one chain and native ones still work, read
Ecosystem payouts have stopped instead: that is a
gas problem, not an RPC one.
The screen
The page opens on a summary band — Ready, Needs attention, Not tested — then a Platform prerequisites card, then four chain families: EVM, UTXO, extended (Solana, Tron, TON, Monero) and custom EVM chains you added yourself.
Each chain collapses to one line: the symbol, the network badge read from
{CHAIN}_NETWORK, a status pill and one sentence naming the single most
important thing wrong with it. The sentence is chosen in a fixed order — a
missing required variable beats an invalid network, which beats a failed check,
which beats a warning — so the line is the next thing to fix, not a summary.
Expanding a chain gives four blocks:
| Block | What it holds |
|---|---|
| Environment contract | Every .env key this chain reads, whether it is set, and a sanitised preview (host only for URLs, never a secret). Missing required keys are pulled to the top in amber with a copy button |
| Prerequisites | Vault unlocked, master wallet present and enabled, active tokens on the current network, and — for the licensed chains — the licence and the chain service being installed |
| Live diagnostics | The last probe result, with a Run full test / Re-run test button |
| Will it work? | The probe results mapped onto platform flows: Balances, Native deposits, Token deposits, Withdrawals, Realtime watching |
Will it work? is the part to read. A green RPC check with a red
Withdrawals line means the endpoint is fine and something else — a locked
vault, a missing master wallet, a node that will not accept
eth_sendRawTransaction — is stopping payouts.
It is a report, not a control panel. There is no status toggle on it, no field that edits an endpoint, and no per-chain enable. Where those levers actually live is the last section of this runbook.
The other place chain state appears is the Ecosystem overview
(/admin/ecosystem), whose chain table carries Chain, Status,
Endpoints, Custody addresses, Gas and Last probe — the last of
which is the stored verdict from this page. Every row on it links straight back
here.
Running the test
chain=PLATFORM for the shared infrastructure instead.Three ways to trigger it: Test all chains in the page header (which queues
PLATFORM first and then every chain, three at a time), Test platform on the
prerequisites card, and the per-chain button inside an expanded card.
It only contacts endpoints you have already configured in .env or the custom
chain table — the request cannot point the server at an arbitrary URL, which is
why it needs only view.ecosystem.blockchain rather than an edit permission.
Nothing is written on-chain and no secret is returned.
requirements/test.post.ts declares audit: false. It runs read-only probes
against configuration somebody else already saved, so there is nothing to
attribute. Do not go looking for it in System → Audit Trail.
Results are stored, in Redis under eco:blockchain:diag:{CHAIN} with a
seven-day TTL, which is why the page can show a verdict after a reload and
why the Ecosystem overview can report a chain degraded. A chain with no stored
entry has never been tested from this install, or the result has aged out — the
page says Not tested yet rather than inventing a pass.
What an EVM test actually checks
| Check | What it does | Passes when |
|---|---|---|
| Network configured | Reads {CHAIN}_NETWORK and matches it against the chain's own network list |
The value is one of the listed names |
| HTTP RPC | eth_chainId and eth_blockNumber, in parallel, over HTTP with an 8-second timeout |
The chain id parses and matches the id configured for this network |
| WebSocket RPC | Opens the socket at {CHAIN}_{NETWORK}_RPC_WSS, reads the network and the block number, 10-second timeout |
It connects and the chain id agrees. Skipped — not failed — when no WSS URL is set |
| Tx history & explorer providers | Probes the whole provider chain in the order the runtime uses | At least one provider answers |
| RPC method support | Calls nine JSON-RPC methods the deposit, withdrawal and balance flows use | None answers -32601 (method not implemented) |
The nine methods are eth_getBalance, eth_call, eth_gasPrice,
eth_estimateGas, eth_getTransactionCount, eth_getLogs,
eth_getBlockByNumber, eth_getTransactionReceipt and
eth_sendRawTransaction. A method that exists but rejects the deliberately
minimal parameters counts as supported; only "not implemented" is a failure.
This is the check that catches a cut-price RPC provider whose free tier omits
eth_getLogs — token deposits stop, native ones keep working, and nothing else
in the product explains why.
A chain-id mismatch is reported in words rather than as a bare failure:
RPC reports chain id 137, but this chain is configured as 1. That is the
signature of a copy-pasted endpoint pointing at the wrong network, and it is
worth checking before you accuse a provider of being down.
The two probes, and why HTTP and WebSocket are asked separately
The platform's own health checks use a matched pair, deliberately built on raw
fetch and ws rather than on an ethers provider:
probeEvmRpcBlockNumber()POSTs{"method":"eth_blockNumber"}to the HTTP(S) endpoint and parses the hex result. Any non-2xx, any JSON-RPC error, or a missing block number throws.probeEvmWssBlockNumber()opens a WebSocket to the WSS endpoint, sends the same request, reads the reply and terminates the socket on every path — answer, error or timeout.
Two endpoints, one question. That is what makes the pair diagnostic: a chain whose HTTP RPC answers and whose WebSocket does not is a different fault from one where both are dead. The first costs you realtime deposit detection and nothing else — the monitors fall back to HTTP polling, which the requirements page reports as a warning on the Realtime watching line, not a failure. The second is a dead chain.
The system health entry states it in one line, and it is worth grepping for:
pm2 logs backend --lines 500 | grep -iE "HEALTH|WSS connection error"Connected to Ethereum (mainnet) via HTTP (latest block: 20913882), but WebSocket
connection failedProving the node is behind
This is the step nothing in the product does for you.
-
Run the chain's test and expand the HTTP RPC row. Its detail line reads
chain id 1 · block #20913882. That number is what your node believes the tip is, at the moment you pressed the button. -
Open a public explorer for the same chain and read its current height. Etherscan, Blockscout, mempool.space — whatever you would use anyway.
-
Compare. A handful of blocks apart is normal propagation. Hundreds is a node that is syncing or wedged. Tens of thousands is a node pointed at a fork, a snapshot, or an endpoint that has silently stopped being maintained.
-
Cross-check inside the platform, for free. On an EVM chain the Tx history & explorer providers row prints a working provider's own block height —
block #20913910 (chainid 1)— from an entirely independent indexer. If a provider pill says one height and your RPC says a much lower one, you have your answer without leaving the admin panel. The two keyless providers are the exception: Blockscout and Routescan print the host that answered rather than a height, so read this off a keyed provider.
A stale node is invisible everywhere else: confirmations are counted against its idea of the tip, so a deposit that the chain confirmed twenty minutes ago is still "unconfirmed" as far as the platform is concerned, forever.
The transaction provider is not the node
An EVM chain has two independent data paths, and they fail independently:
- The node (
{CHAIN}_{NETWORK}_RPC) — balances, gas, nonces, broadcast, and theeth_getLogsscan that finds token deposits. - The tx-history providers — the explorer-class indexers that find native coin deposits and populate transaction history.
tx-provider-probe.ts probes the second set separately, and it keeps no list of
its own: it asks the runtime dispatcher for the plan it would build for this
chain and probes exactly that. Same per-chain order, same key resolution, same
support rules, same circuit-breaker state — so the page cannot disagree with what
a real request does.
There are seven providers — etherscan, blockscout, routescan, ankr,
moralis, covalent, nodereal — and the order is decided per chain. ETH,
Polygon, Arbitrum and Celo lead with Etherscan; Base and Optimism lead with
Blockscout, which needs no key at all; BSC leads with NodeReal; Fantom with
Ankr. Whatever the order, every keyless provider that can serve the chain is
appended to the end of it.
The result is a row of pills, and each state means something specific:
| Pill | Means |
|---|---|
| Serving | The first working provider in order. This is the one actually answering for this chain |
| (plain) | Works, held in reserve behind the active one |
| no key | Supported for this chain, but its key is not configured. The pill names the variable to set |
| (faded) | This provider cannot serve this chain or network at all |
| cooling down | Amber, with a warning icon. The circuit breaker is holding this provider open and skipping it until its cooldown expires; the tooltip says so |
| failed | A key is present and the probe failed. The error says why |
A chain with no keys configured anywhere is no longer automatically degraded.
Where a hosted Blockscout or Routescan instance exists, a keyless provider goes
Serving and the check passes with nothing in .env. The check reports
skipped — with the explanation that native-deposit detection falls back to
scanning blocks over the RPC — only when nothing keyless can serve the chain
either. That is a degraded state you can run in; a configured-but-broken
provider is a real failure and is reported as one.
Where this still bites: Etherscan's free tier is paid-only for BSC (56 and
97), OP Mainnet (10 and 11155420), Base (8453 and 84532) and Avalanche,
with Gnosis joining them on 2026-09-01, and Fantom, Cronos and HECO
are not on Etherscan V2 at all. Base and Optimism are covered keylessly and need
nothing; so is Avalanche, by Routescan rather than Blockscout. BSC,
Fantom, Cronos, HECO and Polygon Amoy have no keyless option at all, and they
get their own section below. Rootstock no longer has its old quirk: its
wallet transaction history goes through the dispatcher like every other EVM
chain, and is served keylessly on both networks — chain id 30 from
rootstock.blockscout.com, 31 from rootstock-testnet.blockscout.com.
Explorer provider failover
Three mechanisms keep a chain's explorer up, and each one changes what you see on the page.
Order is per chain. The Providers, in the order they're tried line on an
expanded chain is that chain's real order, left to right. It comes from
TRANSACTION_PROVIDERS_{CHAIN} if you set one, otherwise TRANSACTION_PROVIDERS,
otherwise a built-in default whose first entry is a provider that is actually free
for that chain. The page prints which of the three it used on an Order from
line under the pills, so if the order surprises you, read it there.
Keys are lists. Every provider key variable may hold several comma-separated
keys, and a provider is only failed after each of them has been tried.
ETHERSCAN_API_KEY="key_a,key_b" is valid, and so is a chain-scoped
BSC_NODEREAL_API_KEY — the chain-scoped list is tried first and the global one
stands behind it as a spare. A value that looks like a URL, or a placeholder like
<your-key-here>, is ignored and reads as no key rather than as a broken one.
Failures are remembered. A provider that fails is skipped for a cooldown on that chain and network: ten minutes for a rejected key, thirty for a plan rejection, sixty seconds for a rate limit, an hour for "does not index this chain", thirty seconds for a network or unclassified error. Those are base figures — the three transient kinds (rate limit, network, unknown) double on each consecutive failure, capped at five minutes; the deterministic ones do not grow. A key that comes back invalid or rate-limited is quarantined across every chain at once, because that is a property of the key. If every provider for a chain is cooling down the dispatcher tries them anyway, so the breaker can never be the sole cause of an outage.
The breaker is in memory, per process, and nothing in the admin panel resets it — the probe reads the same state the dispatcher does, which is exactly why the page is trustworthy. The only reliable clear is the restart you were going to do anyway, on both processes, because each holds its own breaker:
pm2 restart backend
pm2 restart cronAnkr rejects a key that is perfectly valid
Ankr projects carry endpoint security restrictions, and they are the one
provider failure that is not fixed in .env at all. The pill reports what Ankr
said, followed by the change that clears it:
| What Ankr says | What it means |
|---|---|
Origin not allowed |
The project restricts requests by website/domain. The platform calls Ankr from the server and sends no Origin header, so a domain allowlist can never match it — no key, and no .env edit, will ever satisfy it |
API key is not allowed to access from this IP |
The project has an IP allowlist that does not include this server's public outbound address |
API key is not allowed to access blockchain |
The key is fine; this chain is not enabled on the project |
API key not found |
Ankr does not recognise the key — a truncated paste, or a deleted project |
All four are fixed in the Ankr dashboard under project → Settings → Security, not here. For a server-side install, clear the domain restriction and restrict by the server's outbound IP instead; a domain allowlist is meant for browser applications and locks the backend out by design.
The first two are treated as a bad key and quarantine it across every chain for ten minutes, because a domain or IP rule rejects every chain identically. The third is treated as a plan rejection instead, so a key that serves your other chains is not quarantined along with it.
rpc.ankr.com/{chain} without a key now answers every call with "Unauthorized:
You must authenticate your request with an API key". If a {CHAIN}_*_RPC
variable points at a bare Ankr URL, that chain has no node — see
Which variable points at which endpoint.
Forcing a provider on one chain
Pin the order for a single chain and leave every other chain on its default:
TRANSACTION_PROVIDERS_BSC="nodereal,covalent"
TRANSACTION_PROVIDERS_ETH="blockscout,etherscan"Names outside the seven are dropped with a warning in the backend log rather than
failing the boot, so a typo shows up as a shorter pill row, not an error. A
keyless provider that can serve the chain is still appended to whatever you write
— usually what you want; TRANSACTION_PROVIDERS_STRICT="true" turns that off
everywhere.
Restart backend and cron, re-run the chain's test, and confirm the pill row is
the order you asked for.
Chains with no keyless fallback
Five chains have neither a hosted Blockscout instance nor Routescan coverage:
BSC (56 and 97), Fantom (250 and 4002), Cronos (25), HECO (128
and 256) and Polygon Amoy (80002). Polygon mainnet (137) is fine — the
gap is Amoy only. Nothing keyless is appended to their order, so unless you
self-host an instance and name it in <CHAIN>_BLOCKSCOUT_HOST, only a keyed
provider can serve them — and on Cronos and HECO no provider indexes the chain
at all, keyed or not.
BSC is the one where a keyed provider is the normal answer for a production install: Etherscan's free tier stopped covering 56 and 97 in November 2025. Without one of the following, native-deposit detection on BSC runs on the RPC block scanner alone.
| BSC network | What to set |
|---|---|
| Mainnet (56) | NODEREAL_API_KEY — free tier, and the BNB-Chain-endorsed replacement for the retired BscScan API. ANKR_API_KEY, MORALIS_API_KEY and COVALENT_API_KEY also serve it |
| Testnet (97) | MORALIS_API_KEY or COVALENT_API_KEY only. NodeReal and Ankr do not index chain id 97 |
| Either | A paid Etherscan plan on ETHERSCAN_API_KEY or BSC_EXPLORER_API_KEY, or a self-hosted Blockscout instance named in BSC_BLOCKSCOUT_HOST |
The testnet split is worth knowing because the two halves of the system disagree about it. The probe resolves every provider by chain id, so with a key present it reports Ankr and NodeReal as failed on 97, correctly. The dispatcher's own support check sees only the chain symbol, so it lists them as runnable and discovers the truth at request time — one wasted attempt, after which the breaker skips that provider for an hour.
Which variable points at which endpoint
The panel reads .env and reports what it finds. It cannot write it. There
is no field on this screen that changes an endpoint, and there never will be —
the same rule as everywhere else in the platform (see
The admin panel, What the panel cannot do).
| Family | Keys that select the endpoint |
|---|---|
| EVM (ETH, BSC, POLYGON, FTM, OPTIMISM, ARBITRUM, BASE, CELO, RSK, HECO, CRONOS, MO) | {CHAIN}_NETWORK selects the network; {CHAIN}_{NETWORK}_RPC is the HTTP endpoint; {CHAIN}_{NETWORK}_RPC_WSS is optional; {CHAIN}_EXPLORER_API_KEY is tried before the global ETHERSCAN_API_KEY, not instead of it |
| UTXO (BTC, LTC, DOGE, DASH) | {CHAIN}_NODE picks the provider (mempool, blockcypher, node); {CHAIN}_MEMPOOL_API_URL overrides the esplora mirror list; BLOCKCYPHER_TOKEN is shared across all four |
| Solana | SOL_NETWORK only. There is no custom RPC URL — the service always uses the public cluster endpoint. SOLANA_RPC_URL is read by one admin cost estimate and nothing else |
| Tron | TRON_NETWORK, then TRON_MAINNET_RPC / TRON_SHASTA_RPC / TRON_NILE_RPC, plus TRON_API_KEY |
| TON | TON_NETWORK, then TON_MAINNET_RPC / TON_TESTNET_RPC and the matching ..._API_KEY |
| Monero | XMR_DAEMON_RPC_URL and XMR_WALLET_RPC_URL. XMR_NETWORK selects nothing — it only drives address-prefix validation and must match whatever monerod is actually running |
| Custom EVM | Auto-managed from the Custom Chains admin. Do not hand-edit those keys in .env; they are rewritten on every reload |
Two traps the report calls out by name because they read as working:
- The concrete key name depends on the network. Set
ETH_NETWORK=mainnetand the RPC key isETH_MAINNET_RPC; the page shows the generic pattern with a{NETWORK}placeholder until the network resolves, and tells you to set the network first. - Polygon's mainnet network name is
matic, notmainnet. An invalid value fails provider initialisation with "Chain ID not found".
Providers are built once and cached at module load. Correcting an RPC URL in
.env and reloading the admin page changes nothing at all — the running process
still holds the old provider.
pm2 restart backend
pm2 restart cronRestart both. The scheduler is a separate process with its own cached providers, and it is the one that runs the deposit verification and withdrawal reconciliation jobs described below. A web-only restart leaves those still pointed at the dead endpoint.
What stops, and in what order
A dead or stale endpoint on one chain produces this sequence. Knowing it is what stops you from looking in the wrong place.
-
verifyPendingEcoDeposits(every 60 seconds) finds nothing to finalise. It is the only job that drains the pending-deposit set, and it decides by confirmation depth measured against the node's tip. A stale tip means the depth never grows. -
The customer's deposit has no transaction row at all. An unconfirmed ecosystem deposit lives in Redis; the transaction row is written only when confirmations land, already
COMPLETED. So "there is no row" is the normal appearance of a stuck ecosystem deposit — it is not evidence that nothing was detected. Full detail in A customer paid and the balance did not move. -
Withdrawals are debited and never broadcast. The wallet is debited when the customer submits. If the chain provider cannot be reached, the payout never leaves.
-
ecosystemWithdrawRecon(every 5 minutes) re-enqueues them. It sweepsPENDINGecosystem withdrawals older than three minutes that the in-memory queue is not tracking and puts them back on it. With the endpoint still dead they fail again, and the cycle repeats until you fix the endpoint or the row ends up needing a human. -
Some rows end up where nothing automated will ever move them. A row that reached
PROCESSINGwith no transaction hash on a non-UTXO chain is never auto-reverted — the platform cannot prove the transaction was never broadcast, and reverting would risk paying twice. Those are thestrandedrows on the Ecosystem overview's review queue. See Ecosystem payouts have stopped.
The customer-visible shape of all this is: deposits that "never arrive" and withdrawals that sit in the queue. Neither points at an RPC endpoint on its own.
UTXO chains fail differently
Bitcoin, Litecoin, Dogecoin and Dash have no block-height check on this page,
because they have no eth_blockNumber. Their test probes the provider the
factory would actually pick:
- Esplora API reachable — walks the mempool.space / litecoinspace mirror list in order and reports the one that answered plus its tip height. Failing over past a dead mirror is a warning, not a failure.
- Fee rate tier resolves — confirms
BTC_FEE_RATE_PRIORITYnames a tier the provider actually returns. - BlockCypher API — proves reachability and the token, and prints the chain height it reports.
- Bitcoin Core RPC (only when
BTC_NODE=node) —getblockchaininfo, and it fails outright if the node's chain does not matchBTC_NETWORK, or warns ifblocksis behindheaders. That is the one UTXO check that names a sync gap in so many words:Node not synced: 812004/812391 blocks.
The factory's silent fallbacks are mirrored on the page rather than hidden:
node is BTC-only and falls back to BlockCypher elsewhere; Dogecoin and Dash
fall back to BlockCypher whatever you set; an unrecognised value falls back to
the chain default. The Provider selection row prints selected: x → effective: y so you can see which one is really in use.
Where the symptom shows up is different too. On a UTXO chain a degraded
provider looks like unspent outputs that never become spendable, not a stale
block height. Extensions → Ecosystem → Wallets → UTXO
(/admin/ecosystem/utxo, view.ecosystem.utxo) lists them, one row per
outpoint:
| Column | Read it as |
|---|---|
wallet |
The custodial wallet the output belongs to (rendered as its currency) |
amount |
The value of the output, to 8 decimals |
status |
UNSPENT (available), LOCKED (reserved for an in-flight withdrawal) or SPENT (confirmed on-chain). Defaults to UNSPENT. Read it from the row, not the column — see below |
index |
The output index — a UTXO is a transaction id plus this |
script |
The locking script |
createdAt |
When the platform recorded it |
status is an ENUM on the model, but the list column renders it through a
boolean badge, and any non-empty string is truthy. So every row is painted
green Available, including the spent and locked ones. The row's view dialog
reads the real value and labels it Unspent, Locked or Spent — that
is the only place on this screen the status is trustworthy.
A pile of recent rows on one chain still Unspent in the view dialog while withdrawals fail means the provider is answering for reads and failing on broadcast or fee estimation. A chain with no new rows at all while customers insist they have sent coins means detection itself is down.
Turning a chain off
Sometimes the right answer is to stop taking deposits on a chain until its endpoint is fixed. What that lever is depends on the family, and it is not one switch.
| Chain | Where the switch is |
|---|---|
| SOL, TRON, TON, XMR, MO | /admin/ecosystem/blockchain/{productId} — the chain add-on's own page. Its header carries Enable / Disable |
| Custom EVM chains | The Custom Chains admin, /admin/ecosystem/custom-chain |
| Built-in EVM and UTXO chains | There is no chain-level switch. These are compiled in, not installed. The lever is per token, on Ecosystem → Trading → Tokens (/admin/ecosystem/token, edit.ecosystem.token) |
Nothing in the product links to /admin/ecosystem/blockchain/{productId} — not
the requirements page, not the Ecosystem overview (whose rows all go to the
requirements page), and not the Extension Manager, which sends a blockchain
product to /admin/system/extension/{productId} instead. You reach it by typing
the URL.
The productId is the one on that chain's card in System → Extension
Manager (/admin/system/extension?type=blockchain). Note also that the
Enable / Disable button is hidden while the add-on's version reads 0.0.1,
which is the not-yet-installed placeholder — install the blockchain add-on
before you expect a switch.
lic/{productId}.lic exists.Every customer who has ever opened the deposit page for that chain already holds a derived address. Turning the chain or its tokens off stops the platform from issuing and using more; it does not stop anyone sending to an address they already have, and it does not un-send what is on its way.
So disable early — while the endpoint is broken and before another day of customers fund addresses you cannot credit — and expect to credit a tail of deposits by hand afterwards.
Disable when the endpoint is broken and the fix is not minutes away, when the node is on a fork or the wrong network (a chain-id mismatch is exactly this), or when the provider is rate-limiting you badly enough that detection is unreliable. Do not disable for a WebSocket-only failure — that costs realtime detection and nothing else.
The fix, end to end
-
Run the chain's test and read the failing check's own error text. It is specific:
HTTP 429,WebSocket connection timeout,RPC reports chain id 137, but this chain is configured as 1,Unsupported: eth_getLogs. -
Rule out staleness even when everything is green. Compare the block height in the RPC row against a public explorer, and against the provider pills' own heights.
-
Run the platform test too.
PLATFORMchecks the vault key and whether it is unlocked, the ecosystem extension row, Redis and ScyllaDB. A locked vault stops signing on every chain and reads as a chain problem on whichever chain you happened to look at first. -
Correct
.env— the key names are on the page, with copy buttons on the missing ones. -
Restart
backendandcron. Not optional; see the warning above. -
Re-run the test, then re-run Test all chains so the Ecosystem overview's stored verdicts are fresh rather than seven days stale.
-
Clear the wreckage. Ecosystem withdrawals that are still
PENDINGare picked up byecosystemWithdrawReconwithin five minutes with no action from you. AnythingPROCESSINGwith no hash, orTIMEOUT, needs a decision on/admin/finance/withdraw/log— read A withdrawal is stuck before you reject one.
Related
- Ecosystem payouts have stopped — the same symptom caused by an empty gas payer instead of a bad endpoint.
- A customer paid and the balance did not move — which of the four deposit pipelines you are in, and what each leaves behind.
- The scheduler and Scheduled jobs reference — the jobs named on this page, their cadence and what stops when they stop.
- Troubleshooting — the platform-wide checks.