Around Go: blockchain infrastructure · 3 MIN READ

Nonces, fees and unknown outcomes: one durable owner per account

Coordinate transaction intent and account nonce allocation before retrying a send.

Two Go workers can read the same pending nonce and sign conflicting transactions. A process-local mutex helps only while one process owns the account; it does not coordinate replicas or survive a crash. Give each business intent a stable identity, persist its nonce and signed transaction identity under one ownership protocol, and reconcile unknown send outcomes before allocating new work.

blockchain · A MAP OF THE IDEA

  1. Stable business intent
  2. Reserve nonce durably
  3. Sign + record identity
  4. Send then reconcile

Useful when

  • Coordinate transaction intent and account nonce allocation before retrying a send.
  • Makes the owner and the failure boundary explicit.

Watch out

  • A send timeout is not proof that the transaction was rejected.
  • Run native service and failure tests in your own development environment.

Implementation & operation cost: Additional state and tests must be justified by the demonstrated failure; this lesson is not a requirement for every Go program.

01

The contract and the failure

Two Go workers can read the same pending nonce and sign conflicting transactions. A process-local mutex helps only while one process owns the account; it does not coordinate replicas or survive a crash. Give each business intent a stable identity, persist its nonce and signed transaction identity under one ownership protocol, and reconcile unknown send outcomes before allocating new work.

02

Work through the example

Distinguish prepared, submitted, pending, included, reverted and finalized states. An inclusion receipt with failed status is not a successful business effect. EIP-1559 fee cap, priority fee, gas limit and value have different meanings. A replacement may use the same nonce but a different transaction hash and policy-approved fees; keep the business intent stable and record the replacement chain.

go
package main

import "fmt"

type Allocator struct {
	next     uint64
	reserved map[string]uint64
}

func (a *Allocator) Reserve(intent string) uint64 {
	if nonce, ok := a.reserved[intent]; ok {
		return nonce
	}
	nonce := a.next
	a.next++
	a.reserved[intent] = nonce
	return nonce
}
func main() {
	// Single-owner model: the durable multi-process implementation is separate.
	a := Allocator{next: 42, reserved: map[string]uint64{}}
	fmt.Println(a.Reserve("invoice-7"), a.Reserve("invoice-7"), a.Reserve("invoice-8")) // 42 42 43
}
Read the code

Repeating the same business intent reuses its reservation rather than consuming another nonce. The model assumes one owner and intentionally does not persist or sign transactions. A production allocator must atomically store intent and reservation, prevent concurrent owners from diverging and reconcile reservations after restart or account activity outside the service.

03

Production decisions

A send timeout is not proof that the transaction was rejected. Retrying with a fresh nonce can repeat a transfer; blindly retrying the same underpriced transaction may not solve inclusion. PendingNonceAt is an observation, not a distributed reservation. Test concurrent intents, duplicate requests, external account activity, fee replacement, receipt absence, reorg and restart between signing and send.

04

Explain it in an interview

SendTransaction timed out. Is allocating a fresh nonce and sending the transfer again safe? No. The original outcome may be unknown. Reconcile the existing signed intent, hash and nonce before choosing a policy-controlled retry or replacement. Describe the state before the operation, its owner, the failure between steps and the evidence you would test. Distinguish what this example demonstrates from the infrastructure a production service still needs.

TAKE THIS WITH YOU

Coordinate transaction intent and account nonce allocation before retrying a send. No. The original outcome may be unknown. Reconcile the existing signed intent, hash and nonce before choosing a policy-controlled retry or replacement.

Check your understanding

SendTransaction timed out. Is allocating a fresh nonce and sending the transfer again safe?

Go to the source

Progress stays in this browser. No account needed.