Hyperliquid's public API tells you about an order after a block includes it. At that point the order is already on the book, filled or rejected. Everyone who watches the public feed sees it at the same moment. The Hyperliquid mempool shows the same order earlier, while it is still a signed request that travels between nodes.
We measured the gap from AWS Tokyo (ap-northeast-1). For 427,020 orders from the 10 most active Hyperliquid traders, Dwellir's gRPC mempool stream (StreamMempoolTxs) delivered 95.7% of them before Hyperliquid's public WebSocket did. The median lead was 357 ms.
The Short Answer
| Metric (29 Oct 2026, 15 minutes, AWS Tokyo) | Result |
|---|---|
| Orders matched on client order id | 427,020 |
| Seen on the mempool stream first | 95.7% |
Median lead over the public orderUpdates WebSocket | 357 ms |
| Middle 50% of leads (p25 to p75) | 292 to 449 ms |
| 90% of orders arrived at least | 199 ms early |
| Public orders with a client order id that also appeared in the mempool | 99.4% |
| Mempool records per second | about 29 (one client block each) |
| Signed actions per second | about 22,000 |
Hyperliquid produces blocks in less than a second, so a third of a second is a large share of one block interval. Hyperliquid's order book rules let a trader act on that head start. The next sections show how.
What Is in the Hyperliquid Mempool?
Users sign actions and send them to a node. Nodes gossip those actions to each other in batches called client blocks, and the block proposer picks them up for consensus. A non-validating node that peers with the network receives these client blocks before any block includes them.
Dwellir's Hyperliquid gRPC API exposes that feed as StreamMempoolTxs. Each record is one client block, stamped with the time the gateway received it:
["2026-10-29T11:50:38.307729883", {
"tx_hash": "0x63ce9aab0a5bc58a...",
"signed_actions": [{
"signature": {"r": "0xad66...", "s": "0x5780...", "v": 27},
"action": {"type": "order", "grouping": "na", "orders": [
{"a": 0, "b": true, "p": "81459", "s": "12.47108", "r": false,
"t": {"limit": {"tif": "Alo"}}, "c": "0x7849acc2c6c2f6f0fe4bc80ef13d1504"}
]},
"nonce": 1793274638200
}]
}]Every action arrives exactly as the user signed it. a is the asset id (0 is BTC perp) and b is the side. p and s are price and size, t is the order type and c is the optional client order id. The feed also includes cancels, modifies, TWAP orders, leverage changes, transfers and validator votes.
In our 15-minute window the stream carried, per second:
| Action type | Per second |
|---|---|
cancelByCloid | 10,134 |
order | 9,290 |
cancel | 2,146 |
batchModify | 599 |
modify | 189 |
Most of this is market makers quoting and pulling quotes. The rest (TWAPs, transfers, leverage changes, vault actions) is a few hundred actions a second.
Why Is a 357 ms Lead an Edge on Hyperliquid?
Hyperliquid does not process a block's actions in arrival order. Within each consensus batch, the block runs:
- Actions that send no GTC or IOC order to a book. Post-only (
Alo) orders are in this group. - Cancels.
- Actions that send at least one GTC or IOC order.

A cancel in the same block as an incoming IOC order therefore runs before the IOC. A market maker can see a large aggressive order in the mempool and send a cancel. If the cancel reaches the same block, it runs first. With the public API, the maker learns about the IOC only after it fills against their quote.
This is the main edge. It helps market makers who must protect their quotes from toxic flow. The mempool also helps in these ways:
- See liquidity before it rests. Our sample included a $1.8 million post-only BTC bid. At the median lead, a bid like that appears in the mempool 357 ms before the public
orderUpdateschannel reports it. You can adjust your own quotes before the book changes. - Read intent as well as results. Leverage changes, margin transfers, TWAP orders and large cancels show what a trader plans to do. The public API shows only what the exchange did with those requests.
- Measure rejections and inclusion. The exchange rejects some post-only orders because they would cross the book. Match mempool orders to their outcomes to see how often that happens for a strategy, a market or a wallet.
The edge has limits. A pending order can fail, get cancelled or never reach a block. A strategy must treat mempool data as a signal and confirm outcomes from committed block data. The 4.3% of orders that reached the public API first show that gossip does not cover every path into a block.
How Did We Measure the Mempool Lead?
We ran everything on one AWS ap-northeast-1 VM. Both sides used the same clock, so the result has no clock-sync error.
- We watched Hyperliquid's public
tradeschannel onwss://api.hyperliquid.xyz/wsfor 60 seconds and took the 10 most active addresses. - We subscribed to the public
orderUpdateschannel for those 10 addresses. - At the same time we streamed
StreamMempoolTxsfromapi-hyperliquid-mainnet-grpc.n.dwellir.com, which resolves to Dwellir's Tokyo edge from Tokyo. - For each order, we matched the client order id (
cin the mempool,cloidinorderUpdates). The lead is the public receive time minus the mempool receive time. We skipped the first 5 seconds after subscribing, when the public channel sends its backlog.
The run lasted 15 minutes on 29 October 2026, from about 15:04 UTC.

The same distribution as a table:
| Lead (public time minus mempool time) | Share of orders |
|---|---|
| Public first by more than 100 ms | 2.6% |
| Public first by up to 100 ms | 1.7% |
| Mempool first by 0 to 200 ms | 5.8% |
| Mempool first by 200 to 300 ms | 17.8% |
| Mempool first by 300 to 400 ms | 36.8% |
| Mempool first by 400 to 500 ms | 16.4% |
| Mempool first by 500 ms to 1 s | 17.0% |
| Mempool first by more than 1 s | 1.8% |
Three things to know when reading these numbers:
- They understate the lead. Our Python client parsed each multi-megabyte record inside the receive loop, which added about 25 ms of queueing. The compiled
hyperliquid-l1-evalclient measured a median of 4 ms from the Dwellir gateway to the VM. - We matched orders, not cancels. Matching cancels on order id gave a median lead of 266 ms. That match is noisier. A public
canceledevent can come from a modify or a cancel by client order id, and the order-id match misses those. We leave cancels out of the headline. - Some client order ids get reused. About 0.6% of matches had leads above 10 seconds. Those come from reused ids rather than early delivery, and they do not move the median.
How Do You Stream the Hyperliquid Mempool in Python?
The script below follows the BTC perp order flow and prints every order of $250,000 or more as it reaches the mempool. You need Python 3.10 or later, a Dwellir API key with the Hyperliquid gRPC add-on, and a host in or near Tokyo.
python3 -m venv .venv && source .venv/bin/activate
pip install grpcio grpcio-tools
curl -fsSLo v3.proto https://www.dwellir.com/docs/hyperliquid/grpc/v3.proto
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. v3.proto
export DWELLIR_API_KEY=your-api-keyThe reader runs on its own thread and only queues raw records. The main thread does the JSON parsing. If you parse inside the receive loop, the client falls behind a high-volume stream.
import json, os, queue, threading, time, urllib.request
import grpc
import v3_pb2 as pb
import v3_pb2_grpc as rpc
ENDPOINT = "api-hyperliquid-mainnet-grpc.n.dwellir.com:443"
API_KEY = os.environ["DWELLIR_API_KEY"]
COIN, MIN_USD = "BTC", 250_000
RETRY = {grpc.StatusCode.UNAVAILABLE, grpc.StatusCode.DEADLINE_EXCEEDED,
grpc.StatusCode.DATA_LOSS, grpc.StatusCode.RESOURCE_EXHAUSTED}
def asset_id(coin):
"""Perp asset id = index in the public meta universe (BTC is 0)."""
req = urllib.request.Request("https://api.hyperliquid.xyz/info", data=b'{"type":"meta"}',
headers={"Content-Type": "application/json"})
universe = json.load(urllib.request.urlopen(req))["universe"]
return next(i for i, a in enumerate(universe) if a["name"] == coin)
def reader(records):
"""Drain the stream on its own thread; reconnect from the last receive time."""
channel = grpc.secure_channel(ENDPOINT, grpc.ssl_channel_credentials(),
options=[("grpc.max_receive_message_length", 256 << 20)])
gateway = rpc.HyperliquidL1GatewayStub(channel)
last_ns, backoff = None, 1
while True:
try:
# Rewind 1 s on reconnect: each Tokyo gateway stamps its own receive time.
pos = pb.Position(timestamp_ns=last_ns - 1_000_000_000) if last_ns else None
for rec in gateway.StreamMempoolTxs(pb.StreamRequest(position=pos),
metadata=[("x-api-key", API_KEY)]):
last_ns, backoff = rec.timestamp_ns, 1
records.put((time.time_ns(), rec.timestamp_ns, rec.data))
except grpc.RpcError as err:
if err.code() not in RETRY:
raise
time.sleep(backoff)
backoff = min(backoff * 2, 30)
def main():
asset = asset_id(COIN)
records, seen = queue.Queue(maxsize=10_000), set()
threading.Thread(target=reader, args=(records,), daemon=True).start()
while True:
local_ns, node_ns, data = records.get()
_, block = json.loads(data)
for signed in block["signed_actions"]:
action = signed["action"]
if action.get("type") != "order":
continue
for o in action["orders"]:
if o["a"] != asset:
continue
usd = float(o["p"]) * float(o["s"])
key = o.get("c") or (o["p"], o["s"], signed["nonce"])
if usd < MIN_USD or key in seen:
continue # small, or a duplicate after a reconnect
seen.add(key)
side = "BUY " if o["b"] else "SELL"
tif = next(iter(o["t"].get("limit", {}).values()), "trigger")
print(f"{side} {o['s']:>9} {COIN} @ {o['p']:>8} ${usd:>12,.0f} {tif:<4}"
f" node->you {(local_ns - node_ns) / 1e6:5.1f} ms")
if __name__ == "__main__":
main()From our Tokyo VM, the first seconds of output looked like this:
BUY 12.47108 BTC @ 81459 $ 1,015,882 Alo node->you 30.5 ms
SELL 8.5522 BTC @ 81546 $ 697,398 Alo node->you 30.5 ms
SELL 15.48308 BTC @ 81534 $ 1,262,397 Gtc node->you 32.6 ms
BUY 21.90812 BTC @ 81493 $ 1,785,358 Alo node->you 34.9 ms
SELL 7.66691 BTC @ 81605 $ 625,658 Alo node->you 20.5 msAlmost all large orders are post-only quotes. Traders re-send many of them at the same size a few ticks away. To track what a trader intends, follow each client order id through its cancels and modifies rather than reacting to every new order. For a production client, also cap the seen set and move the parsing to a process pool if one core cannot keep up.
Running the Mempool Stream in Production
Drain the stream continuously. The unfiltered feed is about 29 records and 4 to 5 MB per second, and single records reach about 2 MB. Set the client receive limit well above gRPC's 4 MiB default. A client that reads too slowly gets DEADLINE_EXCEEDED or DATA_LOSS and must reconnect.
Leave gzip off for the lowest latency. In our test, gzip raised the median gateway-to-client delay from 4 ms to 18 ms. Turn it on only when bandwidth costs more to you than 14 ms.
Resume with overlap and deduplicate. Each Dwellir Tokyo gateway stamps its own receive time. The same client block can therefore have a slightly different timestamp_ns on another gateway. Reconnect from a second before your last record and drop duplicates on tx_hash or client order id. The StreamMempoolTxs docs list the error codes and resume rules.
Use replay for research. Dwellir keeps about 9 to 12 hours of mempool history. A stream positioned 10 minutes back replayed at about 310 records per second and caught up with the live feed in 60 seconds. That is enough to rebuild a morning's order flow or to recover from a long disconnect.
Run in Tokyo. Dwellir serves the mempool feed from its Tokyo region only. A client in Europe or the US adds that network distance to every record and gives back part of the lead.
How Does Dwellir Compare With Other Hyperliquid Mempool Feeds?
| Option | Transport | Server-side coin filter | Replay | Notes |
|---|---|---|---|---|
Dwellir StreamMempoolTxs | gRPC | No | About 9 to 12 hours | Tokyo region. Same API key and protos as the other Dwellir Hyperliquid streams |
QuickNode MEMPOOL_TXS | gRPC | Yes (coin, coins) | Not stated in the docs | Full mempool firehose by default |
0xArchive mempool channel | WebSocket | Yes (symbol) | None, live only | Pro plan and above. Pairs with its l4_orders channel |
| Your own non-validating node | Files on disk | Your code | Your disk | Needs a gossip peer and 16+ cores. Mempool output adds about 0.5 TB of writes per day |
QuickNode and 0xArchive filter on the server, which saves bandwidth if you follow one or two markets. 0xArchive's mempool docs also show how to recover the signing wallet from each action's signature and how to join pending orders to their outcomes. The same method works on Dwellir's records, because both include the action, nonce and signature exactly as signed.
Dwellir's stream suits teams that already use Hyperliquid gRPC for blocks, fills or order books and want the mempool on the same connection and key. Replay is the main difference from a live-only feed. After an outage you can reconnect and rebuild what you missed. If you would rather run the node yourself, Dwellir also offers Hyperliquid node peering in Tokyo.
Get Started
Hyperliquid's public API can only report what a block already decided. The mempool shows the request about a third of a second earlier. Hyperliquid runs cancels before GTC and IOC orders in a block. A cancel sent on that warning runs first if it reaches the same block.
To try it, enable the Hyperliquid gRPC add-on in the Dwellir dashboard and run the script above from a Tokyo host. For dedicated Tokyo capacity or a node colocated with your strategy, contact the Dwellir team. For how Dwellir's other Hyperliquid feeds compare on latency, see the Hyperliquid data latency benchmark.


