Every Ethereum account has a nonce: a counter that starts at zero and increments by one each time the account sends a transaction. When you sign a transaction, the nonce is included in the signed data. The network will only accept the transaction if the nonce matches exactly what it expects next for your account. If your account has sent 5 transactions, the next one must have nonce 5 (since counting starts at 0). Not 4, not 6, exactly 5.
This simple counter solves two critical problems: it orders your transactions and it prevents replay attacks. Without nonces, someone could take a signed transaction you already sent and broadcast it again, draining your account by replaying the same transfer over and over.
The nonce solves two problems at once:
Ethereum guarantees that transactions from the same account are processed in nonce order. If you send three transactions with nonces 0, 1, and 2, they will execute in exactly that order, regardless of when they arrive at different nodes. This is critical for operations that depend on sequence, like approving a token and then transferring it.
Because each nonce can only be used once, a signed transaction cannot be broadcast again after it has been confirmed. If someone captures your signed transaction and tries to replay it, the network will reject it because that nonce has already been consumed. Without this, a single signed "send 1 ETH" transaction could be replayed indefinitely.
The nonce must be exactly the next expected value. If your account's current nonce is 5 and you submit a transaction with nonce 7 (skipping 6), the node will not reject it outright. Instead, it will hold the transaction in the mempool, waiting for nonce 6 to appear. But nonce 6 never comes, so nonce 7 and everything after it is stuck. This is called a nonce gap, and it is one of the most common issues when building applications that send transactions programmatically.
Nonce gaps typically happen when:
If a transaction is stuck in the mempool (typically because the gas price was too low), you can replace it by sending a new transaction with the same nonce but a higher gas price. The node will drop the old transaction and accept the new one. Most wallets expose this as a "Speed Up" feature.
To cancel a pending transaction, you send a transaction to your own address with the same nonce and a value of 0 ETH (but a higher gas price). This effectively fills the nonce slot with a no-op, and the original transaction is discarded.
// Replace a stuck transaction (same nonce, higher gas)
tx := types.NewTransaction(
6, // same nonce as the stuck tx
toAddress,
value,
gasLimit,
newHigherGasPrice, // must be at least 10% higher
data,
)
// Cancel: send 0 ETH to yourself with the same nonce
cancelTx := types.NewTransaction(
6, // same nonce
myOwnAddress, // send to yourself
big.NewInt(0), // 0 ETH
21000, // minimum gas for a simple transfer
evenHigherGasPrice,
nil,
)
When you build a backend service that sends transactions (a relayer, a bot, an automated system), nonce management becomes one of the hardest problems to get right. You cannot simply call eth_getTransactionCount before each transaction, because if you send two transactions in quick succession, the second call might return the same count as the first (the first transaction has not been mined yet).
Common strategies include:
eth_getTransactionCount with the "pending" parameter to resync when needed// Get the pending nonce (includes unconfirmed txs in the mempool)
nonce, err := client.PendingNonceAt(ctx, account)
// vs. confirmed nonce (only counts mined transactions)
nonce, err := client.NonceAt(ctx, account, nil)
// The difference between the two tells you how many txs are pending
pending := pendingNonce - confirmedNonce
There is a second type of nonce on Ethereum that is less well known. Every contract account also has a nonce, which increments each time the contract deploys another contract using the CREATE opcode. This nonce is used to deterministically compute the address of the newly created contract: address = keccak256(rlp([sender, nonce]))[12:]. This is different from CREATE2, which uses a salt instead of a nonce and produces addresses that do not depend on the deployment order. You can read more about contract deployment in the smart contracts post.
For production-level strategies on how to handle nonces in backend services that send concurrent transactions through multiple nodes, see Nonce Management Patterns.
For the full picture of how transactions travel through the network after the nonce is set, see Sending Transactions on Ethereum.