Halving transaction submission latency with eth_sendRawTransactionSync

By Sam Battenally, Hai Nguyen and Thanh Nguyen. Special thanks to Lin Oshitani and Danilo R for useful feedbacks and comments.

Abstract

The traditionally asynchronous transaction submission and confirmation is no longer suitable for blockchains optimized for latency, such as RISE, MegaETH and Flashblocks chains (Unichain, Base). We introduce a simple eth_sendRawTransactionSync RPC to address key limitations in traditional Ethereum transaction workflows.

By aligning Web3 API behavior more closely with familiar Web2 request-response patterns, eth_sendRawTransactionSync simplifies developer experience, reduces latency, and enhances user responsiveness. This simple RPC is particularly impactful as blockchain architectures evolve toward lower block times and faster responsiveness, bridging the gap between decentralized and traditional application development paradigms.

Motivation

The conventional transaction flow follows an asynchronous model where clients first broadcast signed transactions via eth_sendRawTransaction, then repeatedly poll nodes using eth_getTransactionReceipt until non-null receipts are returned.

In this model, the client submits the transaction and receives a transaction hash immediately, without waiting for the transaction to be included in a block. The client then relies on subsequent polling to determine the transaction’s status. This approach prevents the client from freezing or becoming unresponsive while waiting for the transaction to be mined.

async function sendTransactionAndWaitForReceipt(web3, signedTx, pollingInterval = 200, timeoutMs = 30000) {
  try {
    // Send the signed transaction, returns the transaction hash immediately
    const txHash = await web3.eth.sendSignedTransaction(signedTx);
    console.log(`Transaction sent. Hash: ${txHash}`);

    const startTime = Date.now();
    let receipt = null;

    // Poll for the transaction receipt until it is available or timeout occurs
    while (receipt === null) {
      receipt = await web3.eth.getTransactionReceipt(txHash);

      if (receipt !== null) {
        console.log('Transaction receipt received:', receipt);
        return receipt;
      }

      if (Date.now() - startTime > CONFIG_SYNC_TIMEOUT) {
        throw new Error(`Timeout: Receipt not received within ${CONFIG_SYNC_TIMEOUT} ms`);
      }

      await new Promise(resolve => setTimeout(resolve, pollingInterval));
    }
  } catch (error) {
    console.error('Error sending transaction or fetching receipt:', error);
    throw error;
  }
}

Listing. An example code snippet for sending a transaction and querying its receipt.

Problems

  • Latency Bottleneck. For chains optimized for latency, users expect near-instant feedback and seamless interactions. The inherent latency due to at least two distinct RPC calls can significant hinder the UX, especially for applications that require real-time feedbacks.
  • Developer Experience Challenges. After submitting a transaction via eth_sendRawTransaction, developers must repeatedly call eth_getTransactionReceipt to check if the transaction has been included. This polling loop requires careful timing and error handling.
  • Node Performance. Each eth_getTransactionReceipt call triggers lookups in the node’s database. Repeated or concurrent calls to this RPC at high request rates can strain node resources and degrade performance.

Why Async?

  • Long Blocktime. Ethereum’s average block time is around 12 seconds, meaning a transaction is only finalized after it is included in a proposed block. Since proposing and block propagation take time, a synchronous RPC call that waits for finality would block for many seconds, causing poor responsiveness and poor scalability.
  • DX & UX Considerations. Early blockchain tooling and wallets were designed around asynchronous workflows to avoid freezing user interfaces and to handle the inherent latency gracefully. Polling receipts asynchronously allows better user feedbacks and error handling without blocking the application thread.

Latency Factors

Let’s examine which factors contributing to the total latency.

  1. Network Propagation. The time it takes for the request to reach the block producer across the P2P network.
  2. Mempool Queue. Duration in the pending mempool before being picked into a block.
  3. Block Creation. The time it takes for the receipt to be available after mempool queuing.
  4. Polling Interval Delay. The delay from periodic receipt polling. This value is upper-bounded the case where the receipt becomes available just after a request.

For (1), we can hardly do anything except having our client to be physically close to the block producer. In general, rollups have less propagation time then the L1 in general since the users can send transactions directly to the sequencer (or its replicas). Therefore, in this post, we consider (1) as the baseline for the latency.

(2) mainly depends on the network utilization. High-performant networks are often under-utilized. That is, transactions are processed as soon as they land to the sequencer’s mempool. Therefore, this factor can literally be reduced to a negligible figure (< 1ms) in most of the cases.

(3) is mainly determined by the underlying blocktime. Ethereum or other EVM blockchains have long blocktime. However, with recent attempts to reduce chain responsiveness, we now have blockchains with a few ms (sub)blocktime (e.g, RISE’s \mathtt{Shreds}, MegaETH’s mini-blocks, Base’s Flashblocks), .

(4) is largely depends on the (2), and (3). At the time of submitting a transaction, a client does not know whether the transaction will be included instantly or not. If the polling interval is too short, it overloads the node with failed requests; if too long, it introduces unwanted latency for the client. If we can optimize (2) and (3) to negligible figures, we can certainly remove the need for polling.

The Sync Transaction RPC

As many blockchains optimize for latency (reducing (2) Mempool Queuing Time and (3) Block Creation to as low as a few miniseconds) to enable realtime applications, realtime receipts are an important feature.


Figure. In a low-latency blockchain, transaction receipts are often available right after the transactions land to the sequencer’s mempool. Requiring an additional RPC call introduces unnecessary latency.

We propose introducing a new synchronous RPC method eth_sendRawTransactionSync that combines eth_sendRawTransaction and eth_getTransactionReceipt into a single yet efficient RPC.

The code snippet below outlines a near-complete implementation in reth. As you can see, the code overhead is minimal. Holding HTTP ports open for extended periods can be heavy on resourcing so, TIMEOUT_DURATION should be set to some reasonable duration, say 2s.

async fn send_raw_transaction_sync(&self, tx: Bytes) -> RpcResult<OpTransactionReceipt> {
        const TIMEOUT_DURATION: Duration = Duration::from_secs(2);
        const POLL_INTERVAL: Duration = Duration::from_millis(1);

        let hash = self.inner.send_raw_transaction(tx).await?;

        // Continuously poll the receipt from the shred-funded pending block
        let start = Instant::now();
        while start.elapsed() < TIMEOUT_DURATION {
            if let Some(receipt) = self.pending_block.get_receipt(hash) {
                return Ok(receipt);
            }
            tokio::time::sleep(POLL_INTERVAL).await;
        }

        Err(ErrorObject::owned(
            -32002,
            format!(
                "The transaction was added to the mempool but wasn't processed in {TIMEOUT_DURATION:?}."
            ),
            Some(hash),
        ))
    }

Listing. An example snippet of the eth_sendRawTransactionSync logic.

The TIMEOUT_DURATION=2s and POLL_INTERVAL=1ms are an implementation references and can be configured differently for different chains, depending on the execution performance.

The Gains

  • Latency. Network latency is reduced by half by removing the unnecessity of the two-RPC call paradigm. Transaction receipts could be available almost immediately after the transaction is sent.
  • DX. The new RPC simplifies the entire process and removes the complexities associated with asynchronous programming and manual polling. Developers can write cleaner and more straightforward code, akin to making a standard synchronous API call.
  • UX. The instantaneous transaction confirmation provided by the synchronous method in RISE translates directly into a much smoother and more responsive user experience for individuals interacting with decentralized applications built on the network.
  • Node Performance. For node operators, implementing eth_sendRawTransactionSync is pretty easy, with just over 20 more lines of code. However, it has impactful effects on performance. By eliminating the need for clients to repeatedly query for transaction receipts using the eth_getTransactionReceipt method, the overall number of RPC calls directed at the nodes can be significantly reduced.

A Quick Comparison

The following table summarizes the differences between the traditional async approach and the new sync approach to transaction submission.

Async Method Sync Method
Latency High, at least two round-trips As low as network propagation time
UX Slow responses, laggy UI More responsive, near-instant feedbacks
DX More complex (asynchronous logics, repeated polling) Simple (synchronous calls, direct receipts)
Node Performance Higher load, can strain the node Potentially lower load
Network Efficiency Multiple RPC calls per transaction increase network traffic and latency Single RPC call per transaction reduces network load
Targeted Blockchains Long blocktime, slow execution, fast consensus Short blocktime, fast execution, fast consensus

Experimental Results

We implemented the eth_sendRawTransactionSync with a few lines of code and performed a few benchmarks to illustrate its improvement. In each benchmark, we track the Total Time, which indicates the duration between the time a transaction is submitted until its receipt is available at the client side. We configured our client to be in different locations with different RTT to the tested node.

Baseline Numbers

For each location, we tracked the RPC response time of the benchmarked chains using the eth_blockNumber method as the baseline. The extracted numbers are the average and median of calling eth_blockNumber 50 times, and are recorded in the following table.

Location Average (ms) Median (ms)
Location 1 253 243
Location 2 15 13
Location 3 348 332
Location 4 88 86

Latency Report

We performed a side-by-side comparison between the sync and async methods. For each run, we tracked the Total Time when sending 200 sequential raw-transfer transactions. The following charts and table show the much-improved latency of the sync method compared to the async one (time is measured in miliseconds).

Location Baseline Async Avg Async Med Sync Avg Sync Med
Location 1 243 498 488 247 246
Location 2 13 28 26 15 14
Location 3 332 701 664 334 332
Location 4 86 184 173 88 87

Table. Average and median time for async and sync methods on different locations.

For the async method, the median Total Time numbers are approximately two times the RPC baseline time numbers for all locations. This is expected because a transaction typically requires two RPC calls. It suggests that the time for transaction processing and propagation is tiny compared to RPC time. We also observed frequent fluctuations during the test.


Regarding the sync method, the Total Time is reduced to closely assemble the time for a single RPC call. The sync method also has a more stable performance compared to the async one. As a result, the sync method allows us to save half the time needed to send a transaction and query its status.

Conclusion

The eth_sendRawTransactionSync RPC represents a significant step forward in blockchain interaction design, predominately for chains optimized for low latency. The experiment results demonstrate clear advantages over conventional async methods, with transaction confirmation times reduced by approximately 50%.

In general, halving latency makes blockchain interactions feel more instantaneous and fluid, closer to the responsiveness users expect from Web2 applications. Removing the latency for receipt retrieval means that chains are left with optimizing other parts of RPC connections (routing, proxy, RPC handler, etc.) to fully deliver the real-time experience that current Web2 giants are providing.

4 Likes