Bitcoin, Sui, Aptos, Tron and the Ethereum Beacon API have no native WebSocket: their node software answers HTTP requests and nothing else, so anyone who wants to know about a new block has to keep asking. BoltRPC built a newHeads WebSocket stream for exactly those chains: the gateway watches its own nodes and pushes one message the moment it sees a new head, over the same wss:// URL and the same eth_subscribe call you already use on Ethereum. The obvious question is whether that stream is worth it against simply polling. So we measured it: we subscribed to newHeads over WebSocket on the five chains plus Ethereum as a native control. On the same key, at the same time, we polled each chain’s head every second over HTTPS. After 24 hours the stream had cost between 0.2 percent and 125 percent of what polling cost, depending on the chain. On Ethereum and Sui it also saw new blocks before the poller did; on the per-block chains it delivers each block the moment the gateway sees it, at the chain’s own cadence. This is what that means for your request-unit bill, chain by chain.
The short version. Polling a head every second costs about 255,000 request units a day on every chain, because the call is the same call. A newHeads stream costs 3 request units per message, so its price is the chain’s block rate: 414 request units a day on Bitcoin, 21,000 on Ethereum, 86,000 on Tron, 130,000 on Aptos and 318,000 on Sui. On Sui the stream costs more than 1-second polling and delivers 25 percent more checkpoints; everywhere else it costs less, from 2 to 616 times less.
Why these chains have no WebSocket and what BoltRPC serves instead
Bitcoin Core speaks JSON-RPC over HTTP and has no subscription model. Sui fullnodes expose JSON-RPC and gRPC, not WebSocket. Aptos and the Ethereum Beacon API are REST. Tron’s full node is an HTTP wallet API. None of them let a client say “tell me when there is a new block”.
On BoltRPC each of these chains has a synthetic WebSocket, the Synthetic WS chip on its network page, at the same URL shape as every EVM chain. Today that covers Aptos, Bitcoin, Sui, Tron and the Beacon chains.
wss://endpoints.boltrpc.io/ws/YOUR_API_KEY/{network}
You subscribe with the standard eth_subscribe call and the topic newHeads. The gateway produces the stream from its own node monitoring: every time it observes a new head on the chain, it pushes one message with the head’s identifying fields. Each delivered message is billed at the published weight of eth_subscription, 3 request units, the same as on Ethereum. There is no WebSocket surcharge and no separate plan. On Bitcoin, Sui and Tron regular JSON-RPC calls relay over the same socket; on Aptos and the Beacon API the socket is subscribe-only.
Scope: this is a newHeads stream. Log and pending-transaction topics stay on the chains whose nodes produce them; on these five the head message is the trigger and the reads follow over HTTPS, which is the cheaper pattern anyway (rule 3 below).
How we measured
One Python harness, one API key, six chains in parallel. For each chain it held a WebSocket subscription open and, independently, called the chain’s head-read every second over HTTPS:
| Chain | Stream key | Polled call (3 request units each) |
|---|---|---|
| Sui | sequenceNumber | sui_getLatestCheckpointSequenceNumber |
| Aptos | block_height | GET /v1 |
| Bitcoin | height | getblockcount |
| Ethereum Beacon | slot | GET /eth/v1/beacon/headers/head |
| Ethereum (native WebSocket, control) | number | eth_blockNumber |
| Tron | number | POST /wallet/getnowblock |
For every height the harness recorded the first moment the stream delivered it and the first moment a poll returned it, so lead time is measured per height, not averaged over guesses. The run lasted 24 hours and the minute log has no gap longer than 62 seconds, so the machine never slept. The figures below are the totals as counted, not scaled. The whole exercise cost 2.11 million request units on one key, a small fraction of a month on any plan.
Ethereum is in the table as the control: it has a native WebSocket, so it shows what a stream is supposed to look like.
Table 1: request units per day, stream vs polling
Per day, as counted. Realistic polling is the interval a careful integrator would pick for that chain, since nobody polls Bitcoin every second in production. Multiply any column by your plan’s rate on the pricing page for the monthly figure.
| Chain | Stream messages/day | Stream RU/day | 1 s polling RU/day | Stream vs 1 s polling | Realistic interval | Realistic polling RU/day |
|---|---|---|---|---|---|---|
| Bitcoin | 138 | 414 | 255,147 | 616× less | 30 s | 8,640 |
| Ethereum (control) | 7,165 | 21,495 | 255,201 | 12× less | 4 s | 64,800 |
| Ethereum Beacon | 7,174 | 21,522 | 254,691 | 12× less | 4 s | 64,800 |
| Tron | 28,788 | 86,364 | 254,178 | 2.9× less | 3 s | 86,400 |
| Aptos | 43,171 | 129,513 | 255,012 | 2× less | 2 s | 129,600 |
| Sui | 106,007 | 318,021 | 254,841 | 1.2× more | 1 s | 259,200 |

Three things stand out.
Polling costs the same everywhere, the stream costs what the chain produces. A poller pays for the clock; a subscriber pays for blocks. On a chain with one block every ten minutes that gap is three orders of magnitude.
Why anyone polls Bitcoin every second at all. Nobody chooses to. It happens for two reasons. First, “one block every ten minutes” is an average: the next block can arrive after twenty seconds or after forty-five minutes, so a deposit pipeline that polls every ten minutes is on average five minutes late and sometimes half an hour late. Teams that cannot afford that poll every few seconds to be early enough. They pay for the uncertainty, not for the blocks. Second, multi-chain code usually has one poll loop with one interval, tuned for the fastest chain, so Bitcoin polls along at one second because nobody wrote an exception for it. The stream removes the choice: the message arrives when the block arrives, never late and never for nothing.
The stream is a good proxy for the “right” polling interval. Compare the stream column with the realistic-polling column: Tron’s stream (86,364) is almost exactly a 3-second poll (86,400), Aptos’s stream (129,513) is a 2-second poll (129,600). That is not a coincidence, it is the chain’s cadence. The stream gives you that interval without you having to know it, minus the missed heights that a fixed interval produces when block times jitter.
Sui is the exception and it is worth reading correctly. Sui produces a checkpoint several times a second. A 1-second poller saw 22.1 percent of all checkpoint numbers in the window; the stream delivered 27.6 percent, because it carries the latest checkpoint every time it ticks and skips the ones in between, reporting how many it skipped in a blocks_skipped field. So on Sui the stream costs 25 percent more than 1-second polling and delivers 25 percent more checkpoints. If your Sui integration needs every checkpoint, neither is the tool; the Sui gRPC checkpoint stream is. That stream is billed differently: by bytes delivered, 1 request unit per 24 KB, rather than per message. If it needs “the latest checkpoint, often”, the WebSocket is the cheaper way to get there per checkpoint seen.
Table 2: how much earlier the stream knows
Lead time is the poll’s first-seen time minus the stream’s first-seen time for the same height, so a positive number means the stream was first. Measured per height over 24 hours on the chains that produce heads faster than once a second, with native Ethereum as the control.
| Chain | Heights seen by both | Stream first (share) | Lead p50 | Lead p90 |
|---|---|---|---|---|
| Ethereum (control) | 7,164 | 94.5% | +483 ms | +894 ms |
| Sui | 27,477 | 59.9% | +29 ms | +208 ms |
| Aptos | 3,848 | 50.2% | 0 ms | +98 ms |
The control behaves as a native stream should: on Ethereum the WebSocket beats a 1-second poller on 94.5 percent of blocks, by about half a second at the median. Sui and Aptos tick at the chain’s own sub-second cadence, so against a 1-second poller they come out even or slightly ahead, at a fraction of the request units.
Bitcoin, Tron and the Beacon API produce one head every few seconds or minutes. The stream delivers each one at that rhythm: one message per Tron block (3 s), per Bitcoin block (minutes), per Beacon slot (12 s). A client that polls every second can see a new height up to one chain tick sooner. It pays 2.9×, 616× and 12× the request units for that head start. For a deposit scanner, an indexer or an alerting pipeline the stream is the obvious choice; for a latency-sensitive relay you now know exactly what the head start costs and can decide with numbers.
Two more results from the 24 hours are worth having. On the per-block chains the stream and the poller saw the same heights to within a fraction of a percent, so nothing is lost by switching. And the stream caught 166 Tron blocks in 24 hours that the 1-second poller never returned, because a poll can land between two blocks that arrive close together while the stream delivers both. As on any WebSocket, native ones included, a subscription can be closed by either side and a head produced in that moment is not replayed, so build the client to resubscribe on close and to compare each height with the previous one; the code below does exactly that.
How to cut RPC costs for block tracking: five rules from the data
- Stop polling for heads, subscribe. On every chain except Sui the
newHeadsstream costs less than 1-second polling, from 2× on Aptos to 616× on Bitcoin. A head feed is the one workload where the cheapest option is also the simplest. - If you must poll, poll at the chain’s cadence. The stream’s daily cost is a free hint: Tron 86,000 request units a day equals a 3-second poll, Aptos 130,000 equals a 2-second poll. Polling faster than the chain produces blocks buys nothing but bill.
- Use the stream as the trigger, not the payload. A
newHeadsmessage is 3 request units. Fetch the full block or the logs you need on that trigger instead of fetching on a timer; you pay for blocks that exist, not for checks that came back empty. - Pick the feed by what you need per checkpoint. On Sui, “the latest checkpoint often” is the WebSocket; “every checkpoint” is the gRPC stream, billed by bytes. Choosing the wrong one costs either coverage or money.
- Budget with the published weights before you build. Every method on the pricing page has a fixed request-unit weight. Every stream message is
eth_subscriptionat 3. Multiply by your expected block rate and you have next month’s bill today, which is how the table above was built.
Is polling or WebSocket better for blockchain RPC?
For “tell me when the next block exists”, the stream wins on cost on five of the six chains and sees the block first on Ethereum and Sui, with Aptos a tie. Polling keeps a case in exactly two situations: when you need every checkpoint on a chain that produces several per second, or when you are willing to pay a large multiple for up to one tick of head start on a slow chain. If you are unsure, start with the stream and add a poll only where the numbers above say it buys you something.
What is replacing WebSockets?
Nothing is replacing them for this job, but two neighbours exist. Server-sent events are a one-way stream over plain HTTP; the Beacon API’s own /eth/v1/events endpoint uses them. gRPC streams are typed and efficient; Sui’s checkpoint subscription over native gRPC is available on BoltRPC, billed by bytes delivered (1 request unit per 24 KB) instead of per message. Both are better when you want a typed, exhaustive feed. The WebSocket newHeads stream is better when you want one URL pattern and one subscribe call across every chain on the platform.
Are WebSockets outdated?
No. What is outdated is the assumption that a chain without a WebSocket node has to be polled. The measurement above is the difference: the same integration code that streams Ethereum heads streams Bitcoin heads, at 3 request units per block instead of 3 per second.
What the messages look like
One message per chain, captured live on 2026-09-16. Fields are the chain’s own identifiers, so a Sui message carries a checkpoint digest and a Beacon message carries a slot and roots.
// Sui
{"sequenceNumber": "323380598", "digest": "CwTUKwN4ctcamoP2FSmCaGifVB7368u8sRSuLBKPVaJh", "epoch": "1252", "previousDigest": "CFginD8U3T4dtQ5PWXgckhWQeEAz1DuHHHL2C8qZTxDD", "timestampMs": "1789576944224", "networkTotalTransactions": "5938740102"}
// Aptos
{"block_height": 1049585772, "ledger_version": 7233272951, "ledger_timestamp_ms": 1789576944, "epoch": 17304, "chain_id": 1}
// Tron
{"number": 86301593, "hash": "000000000524db99...", "parentHash": "000000000524db98...", "timestamp": 1789576944000}
// Ethereum Beacon
{"slot": 15229410, "block": "0x01bd7b25...", "parent_root": "0xf8743ccb...", "state_root": "0x37491fc0..."}
// Bitcoin
{"height": 967283, "hash": "00000000000000000000a8240273530b2b407c9c611376a1b560e723a85fbc93", "time": 1789564491, "mediantime": 1789561208}
Subscribe in 20 lines of Python
The harness is longer, but the core is this:
import asyncio, json, websockets
URL = "wss://endpoints.boltrpc.io/ws/YOUR_API_KEY/tron" # or sui, aptos, bitcoin, ethereum-beacon
async def main():
async with websockets.connect(URL) as ws:
await ws.send(json.dumps({"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newHeads"]}))
print("subscription:", json.loads(await ws.recv())["result"])
async for raw in ws:
msg = json.loads(raw)
if msg.get("method", "").endswith("subscription"):
head = msg["params"]["result"]
print("new head", head) # 3 request units, billed per delivered message
asyncio.run(main())
Swap the network slug and the same loop runs on every chain in this article. On Bitcoin, Sui and Tron you can send ordinary JSON-RPC calls over the same connection; on Aptos and the Beacon API keep a separate HTTPS client for reads.
How to pick the right feed
newHeadsis the topic on these chains. Fetch logs or pending transactions over HTTPS on the trigger, which is the cheaper pattern anyway (rule 3).- On Aptos and Sui each message carries the latest head at the tick and the number of heights since the previous message, so a sub-second chain never floods your client; the gRPC checkpoint stream is the feed for every checkpoint on Sui.
- On Bitcoin, Sui and Tron ordinary JSON-RPC calls relay over the same socket; on Aptos and the Beacon API keep a separate HTTPS client for reads.
FAQ
How do I reduce RPC costs for a block feed?
Subscribe to newHeads instead of polling, fetch full blocks or logs only when a message arrives and on fast chains pick the feed that matches how many heads you actually need. On the chains measured here that turns a fixed 255,000 request units a day into the chain’s own block count times 3.
Does BoltRPC support WebSocket on Bitcoin, Sui, Aptos, Tron and the Beacon API?
Yes, for new heads. The gateway produces a newHeads stream from its own node monitoring on each of these chains and serves it at wss://endpoints.boltrpc.io/ws/YOUR_API_KEY/{network}, subscribed with the standard eth_subscribe call.
What does a WebSocket message cost?
Each delivered message is billed at the published weight of eth_subscription, 3 request units, on every chain. The subscribe and unsubscribe calls cost 3 request units each. There is no WebSocket surcharge.
Is WebSocket cheaper than polling?
For a head feed, on five of the six chains we measured, yes: from 2 times cheaper on Aptos to 616 times cheaper on Bitcoin against 1-second polling. On Sui the stream costs about 25 percent more than 1-second polling and delivers about 25 percent more checkpoints.
How much earlier does the stream see a new block?
On Ethereum about half a second at the median, on Sui about 30 milliseconds, on Aptos it is a tie. On Bitcoin, Tron and the Beacon API the message arrives with the block, at the chain’s own cadence; a 1-second poller can be up to one tick sooner at a multiple of the request units.
Does the stream skip blocks?
On per-block chains (Bitcoin, Tron, Ethereum, Beacon) no: over 24 hours the stream and a 1-second poller saw the same heights to within a fraction of a percent. The few differences sit around resubscribes; a height check closes them. On Sui and Aptos the stream carries the latest head at each tick and reports the number of skipped heights in the message.
What happens on reconnect?
The client resubscribes. A head produced during that moment is not replayed by any WebSocket, native ones included, so build the client to resubscribe on close and to fetch any height it skipped; the Python example above shows the loop.
Can I use the same code on every chain?
Yes. The URL pattern, the eth_subscribe call and the newHeads topic are identical on every network. The fields inside the message follow the chain.
How do I reproduce these numbers?
The harness is a single Python file with no dependencies beyond websockets. Run it against your own key for an hour and you will see the same shape.
Related
- WebSocket vs HTTP for RPC connections
- Ethereum WebSocket events guide
- Sui · Aptos · Bitcoin · Tron · Ethereum Beacon
- Pricing and request-unit weights
Try it on your own key
Every plan and the free trial include WebSocket on every network. Subscribe to newHeads on Bitcoin, Sui, Aptos, Tron or the Beacon API and watch the request-unit counter on the Usage page do the arithmetic above for you.
Start your free 14-day trial: dashboard.boltrpc.io/signup
