Docs / Guides / Polling vs webhooks
Polling vs webhooks for TRON deposits
The polling loop is a weekend project. The polling loop that never loses money is not.
The weekend version
while (true) {
const block = await tronWeb.trx.getBlockByNumber(++height);
for (const tx of block.transactions ?? []) {
if (isUsdtTransferToUs(tx)) creditDeposit(tx);
}
await sleep(3000);
}
It works in the demo. Then it meets production.
The real checklist
- Finality. Is that block final, or will it reorg? Query the wrong node view and deposits vanish after you credit them (the missing-transaction trap).
- Crash recovery. Your process dies at block 85,101,201. Where do you resume? Without a persisted cursor you skip blocks (lost deposits) or re-scan (double credits) — you need both a cursor and idempotent writes.
- Catch-up. After 30 minutes of downtime you're 600 blocks behind while the chain adds a block every 3 seconds. Sequential polling never catches up; now you're writing concurrent fetching with ordered processing.
- Rate limits. Public endpoints throttle aggressively; even paid tiers enforce QPS ceilings. Full-block scanning is 2 requests per block, ~58k/day — your catch-up burst needs a rate limiter or it gets you 403'd mid-recovery.
- Receipt parsing. Failed transfers sit in blocks too (
contractRet !== 'SUCCESS'), calldata parsing misses contract-internal transfers, and USDT amounts need decimal-safe handling —parseFloaton money is how accounting drifts. - Delivering to yourself. Detecting the deposit is half the job; your downstream service is sometimes down, so you also build retries, backoff, a dead-letter store, and an audit log.
Each item is a few days and an incident. Every team building on TRON writes this same scraper, badly, once.
When polling is right anyway
Honest answer: sometimes. If you already run TRON nodes, need sub-block custom analytics, or have compliance reasons to keep everything in-house — build the pipeline; the checklist above is your spec. For everyone else, deposit detection is undifferentiated plumbing.
The webhook trade
A watch API inverts the model: you register addresses once, and a service that already solved finality, cursors, catch-up, rate limiting and retries POSTs you a signed event when a deposit is confirmed — with an events API to reconcile whenever you're paranoid (be paranoid: it's money).
const th = new TronHooks('tw_live_...');
await th.watches.create({ address: 'T...', assetFilter: 'USDT', webhookUrl: 'https://you.dev/hook' });
// done — verify signatures on arrival, dedupe on event_id
tronhooks runs the loop so you don't: confirmed-only events, signed deliveries, full audit trail. Free for 3 addresses — or skip code entirely with Telegram alerts.
5-minute quickstart →