Skip to main content
Since the Merge, Ethereum execution clients require a consensus layer (beacon node) alongside them. This adds complexity when standing up a private network from scratch. Geth provides three solutions depending on how much realism your use case requires.

Simulated backend

In-process, in-memory simulation for Go unit tests and CI pipelines.

Dev mode

Single-node, no-networking environment with instant block production. Ideal for local contract development.

Kurtosis

Full multi-client testnet with real consensus and execution clients. Best for integration testing.

Option 1: Simulated backend

If you are writing Go code and need an Ethereum environment for tests or CI, the simulated backend is the simplest option. It runs entirely in memory inside the same process as your tests — no separate process, no ports, no disk. See the Native Bindings documentation for usage details.

Option 2: Dev mode

Dev mode starts a single Geth node that simulates a fully functional Ethereum environment without any networking or external consensus layer. It is intended for fast, iterative development.
geth --dev

What dev mode does

  • Pre-funded account: A random developer account is created, pre-funded with a large balance (10^49 ETH), and automatically unlocked. The private key is printed to the log at startup so you can import it into tools like MetaMask or cast.
  • Instant block sealing: Geth only produces a block when there is at least one pending transaction in the mempool. If --dev.period is set to a non-zero value, blocks are produced on a fixed interval even when empty.
  • No networking: Peer discovery is disabled, the maximum peer count is 0, and there is no listen address. The node cannot connect to or be reached by any other node.
  • In-memory database: Unless --datadir is specified, the chain is stored entirely in memory and is lost when the process exits.
Dev mode is not suitable for production or for testing security properties. The pre-funded account is temporary and stored in a ramdisk — it will be lost if the machine restarts and --datadir is not set.

Dev mode flags

FlagDefaultDescription
--dev(flag)Enable dev mode
--dev.period0Block period in seconds (0 = mine only when transactions are pending)
--dev.gaslimit11500000Initial block gas limit

Example: attach a console

# Terminal 1 — start dev node
geth --dev --http --http.api eth,web3,personal

# Terminal 2 — attach interactive console
geth attach http://127.0.0.1:8545

Option 3: Custom genesis with geth init

For a more realistic private network — for example, one shared among a small team — you can define a custom genesis block and initialise Geth from it.
1

Create a genesis.json file

Define the chain parameters, initial balances, and any network upgrades:
{
  "config": {
    "chainId": 12345,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0,
    "clique": {
      "period": 5,
      "epoch": 30000
    }
  },
  "difficulty": "1",
  "gasLimit": "8000000",
  "extradata": "0x0000000000000000000000000000000000000000000000000000000000000000YOUR_SIGNER_ADDRESS_HERE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "alloc": {
    "YOUR_ADDRESS_HERE": {
      "balance": "1000000000000000000000"
    }
  }
}
Choose a unique chainId that does not conflict with any public network.
2

Initialise the data directory

geth init --datadir /var/lib/myprivatechain genesis.json
This writes the genesis block to the database. Run this on every node that will join the network.
3

Start Geth

geth \
  --datadir /var/lib/myprivatechain \
  --networkid 12345 \
  --port 30303
Connect additional nodes using --bootnodes with the enode URL of the first node.
Post-Merge private networks require a consensus layer running alongside each execution node. For a purely Clique-based (proof-of-authority) private network predating the Merge configuration, this may still work for test scenarios, but a full post-Merge setup requires pairing each Geth instance with a beacon node. Use Kurtosis (below) for that.

Option 4: Kurtosis (multi-client testnet)

Kurtosis is the recommended approach when you need a realistic multi-node test network that includes both execution and consensus clients. Kurtosis automates the orchestration of multiple Geth (and other client) instances alongside beacon nodes, giving you:
  • Multiple execution + consensus client pairs
  • Realistic peer-to-peer networking between nodes
  • Configurable genesis and fork parameters
  • Support for mixed-client environments (Geth + Lighthouse, Geth + Prysm, etc.)
This is the best option for integration testing, client interoperability work, and simulating mainnet-like conditions.
# Install Kurtosis CLI, then:
kurtosis run github.com/ethpandaops/ethereum-package
Refer to the Kurtosis documentation for the full setup guide.

Build docs developers (and LLMs) love