All Blog Posts
Base Flashblocks for RPC operators

Base Flashblocks for RPC operators

By Elias Faltin 11th September 2026 5min read

A Base transaction can have a receipt before its block seals. If your application treats every receipt as final, Flashblocks can make that mistake visible sooner.

Flashblocks publish in-progress block updates about every 200 milliseconds. Base seals the complete block on an approximately two-second cadence. Your client must track which state produced a read or receipt.

This article covers the Flashblocks deployment documented on September 14, 2026. Base plans to replace it with native 200ms blocks through Denim. Mainnet and Sepolia activation dates remain undecided in the migration guide.

The Base network page lists Dwellir endpoints. For a working comparison interface, see the Flashblocks visualizer guide.

Read pending and sealed state separately

On a Flashblocks-aware endpoint, pending refers to the latest in-progress Flashblock state. latest refers to the most recently sealed block.

ReadStateUse
eth_getBlockByNumber("pending", false)In-progress blockShow early transaction inclusion
eth_getBlockByNumber("latest", false)Sealed blockCheck the sealed head
eth_call(transaction, "pending")Flashblock-aware stateSimulate against recent preconfirmed changes
eth_getBalance(address, "pending")Flashblock-aware balanceShow a provisional balance
Pending reads in-progress Flashblock state with about 200ms updates. Latest reads sealed blocks on about a 2s cadence. Keep the block tag in cache keys and reconcile early receipts.

Set API_KEY to your Dwellir key before running this read-only request:

BASH
curl -sS "https://api-base-mainnet-archive.n.dwellir.com/$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["pending",false]}'

Change pending to latest to read sealed state. For JavaScript, install ethers v6 and set DWELLIR_API_KEY:

JAVASCRIPT
import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider(
  `https://api-base-mainnet-archive.n.dwellir.com/${process.env.DWELLIR_API_KEY}`,
);

for (const tag of ['pending', 'latest']) {
  const block = await provider.send('eth_getBlockByNumber', [tag, false]);
  if (!block) throw new Error(`No block returned for ${tag}`);
  console.log(tag, block.number, block.hash, block.transactions.length);
}

The requests can observe different moments. Do not assume they form an atomic snapshot.

Include the network and block tag in cache keys. Pending state can change within the same block number. Avoid caching it indefinitely or treating a placeholder hash as a stable identifier.

Submit and wait for a receipt

eth_sendRawTransaction returns a transaction hash. Your application then waits for a receipt. eth_sendRawTransactionSync combines submission and waiting in one request.

The following snippet requires signedRawTx, a valid signed transaction. Calling it broadcasts that transaction and can incur fees:

JAVASCRIPT
const receipt = await provider.send('eth_sendRawTransactionSync', [signedRawTx]);
console.log(receipt.transactionHash, receipt.status, receipt.blockNumber);

The synchronous submission method can return a preconfirmed receipt. Its fields include execution status, gas used, and logs. A preconfirmed blockHash can be a placeholder.

A 200ms Flashblock interval is not a 200ms request-latency guarantee. Network delay, transaction validity, and inclusion all affect completion. Handle errors and timeouts using the known transaction hash before deciding whether to retry.

Record early results as provisional. After sealing, fetch the transaction receipt again and compare its block against the sealed chain. Keep your normal reorganization handling.

Parse the subscription you requested

Flashblocks endpoints support additional WebSocket subscriptions. Each has a different response shape.

SubscriptionResponse
newFlashblocksFlashblock payloads with an index and incremental state changes
newFlashblockTransactionsPreconfirmed transaction hashes, or full objects when requested
pendingLogsLogs from pending Flashblock execution

The newFlashblocks payload includes payload_id, index, and diff. Index zero also provides the base fields. Do not decode it as an ordinary eth_getBlockByNumber response.

Install ws for this Node.js example. It subscribes to updates and prints the payload without assuming a full-block schema:

JAVASCRIPT
import WebSocket from 'ws';

const ws = new WebSocket(
  `wss://api-base-mainnet-archive.n.dwellir.com/${process.env.DWELLIR_API_KEY}`,
);

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'eth_subscribe',
    params: ['newFlashblocks'],
  }));
});

ws.on('message', (data) => {
  const message = JSON.parse(data.toString());
  if (message.error) console.error(message.error);
  else if (message.params) console.log(message.params.result);
});
ws.on('error', console.error);

Add reconnect handling and state recovery before using this in production. Subscribe to transaction objects with ['newFlashblockTransactions', true]. Use pendingLogs with an address or topic filter when you only need specific events.

The Flashblocks API overview documents newHeads notifications at approximately 200ms on Flashblocks endpoints. A newHeads event alone therefore does not prove block sealing. Query eth_getBlockByNumber("latest") when that distinction matters.

Read pending state with eth_call or eth_getBlockByNumber. eth_sendRawTransactionSync returns a preconfirmed receipt. Stream newFlashblocks, newFlashblockTransactions, or pendingLogs. Query latest to track sealed blocks.

Choose confirmation requirements per operation

A user interface can show provisional results before a withdrawal system permits settlement. Make those decisions explicit in code and in the labels users see.

StateWhat it establishesExample use
Flashblock / pendingPreconfirmation within the current blockProvisional trade status
Sealed / latestInclusion in a sealed Base blockReceipt reconciliation
safeBatch data published to L1Track L1-backed inclusion
finalizedBatch included in finalized L1 dataApply settlement policy

The Base finality specification separates these stages. Canonical Base-to-Ethereum withdrawals also require the seven-day challenge period and bridge steps. A finalized L2 block does not bypass them.

Pending is a Flashblock preconfirmation. Latest is a sealed L2 block. Safe reflects L1 batch publication. Finalized reflects finalized L1 inclusion. Bridge withdrawal rules remain separate.

Check the client before release

  • Keep pending and sealed reads separate in caches, metrics, and UI labels.
  • Store the transaction hash so timeout recovery can check the existing submission.
  • Parse each WebSocket subscription according to its documented response shape.
  • Reconcile provisional receipts and logs after block sealing.
  • Test disconnects, missing updates, and chain reorganizations.
  • Review the Denim migration requirements before its activation on your target network.

Read the Base documentation for method details and the chain reorganization guide for recovery patterns. For keyed Base endpoints, create a Dwellir account.

read another blog post