Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Go-Ethereum (Geth) Administrator & Architecture Guide

Generated June 2026 from ethereum/go-ethereum at f5c62d0

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for node operators, infrastructure engineers, protocol developers, and architects who deploy, operate, secure, or extend Geth. It documents the system architecture, the complete configuration surface, deployment and operations procedures, security hardening, and the internal package design — written from the go-ethereum source at commit f5c62d0 (Go 1.24).

For installation and day-to-day usage, see the companion User Guide. This guide assumes familiarity with Ethereum concepts (accounts, transactions, the EVM, proof-of-stake) and focuses on how Geth is built, wired together, and run in production.


1. Executive Summary

Geth is the official Go implementation of an Ethereum execution-layer (EL) client. It is one process in a two-client node: Geth executes transactions and maintains state, while a separate consensus-layer (CL) client drives proof-of-stake fork choice. The two communicate over the authenticated Engine API.

Aspect Detail
Language / toolchain Go 1.24, cgo (secp256k1, blst)
Role Ethereum execution-layer client
Primary binary geth (cmd/geth)
Companion tools abigen, evm, devp2p, ethkey, era, rlpdump, abidump, blsync, workload, fetchpayload
CLI framework urfave/cli/v2
Storage engines Pebble (default) or LevelDB, plus an "ancient" freezer and Era archives
State model Merkle-Patricia trie over a path-based or hash-based node store; experimental binary trie
Networking devp2p (discovery v4/v5, RLPx transport, eth/snap wire protocols)
External interfaces JSON-RPC (HTTP/WS/IPC), GraphQL, Engine API, metrics
License GNU LGPL-3.0 (library) / GPL-3.0 (binaries)

Important

The single most consequential operational fact: a Geth process is not self-sufficient. Production deployment is always "Geth + a CL client + a shared JWT secret." Plan capacity, monitoring, and incident response around the pair, not Geth in isolation.


2. Architecture

2.1 High-level component diagram

                         ┌──────────────────────────────────────────────┐
                         │                cmd/geth (CLI)                  │
                         │  urfave/cli app · flag parsing · subcommands   │
                         └───────────────────────┬──────────────────────┘
                                                 │ builds
                                                 ▼
        ┌────────────────────────────────────────────────────────────────────────┐
        │                              node.Node                                   │
        │  Service container: lifecycle, account manager, P2P server,              │
        │  RPC stack (IPC/HTTP/WS/Auth), GraphQL, datadir/keystore resolution      │
        └───────┬───────────────────────────────┬───────────────────────┬─────────┘
                │ registers                      │ exposes               │ auth port
                ▼                                ▼                       ▼
   ┌─────────────────────────┐      ┌──────────────────────┐   ┌──────────────────┐
   │      eth.Ethereum       │      │  rpc + internal/      │   │  eth/catalyst    │
   │  (the EL service)       │      │  ethapi + graphql     │   │  Engine API impl │
   │                         │      │  JSON-RPC / GraphQL   │   │  (CL <-> EL)     │
   │  ┌───────────────────┐  │      └──────────────────────┘   └──────────────────┘
   │  │ core.BlockChain   │  │
   │  │  · state processor│  │      ┌──────────────────────┐   ┌──────────────────┐
   │  │  · core/vm (EVM)  │  │      │   eth/downloader     │   │  miner (payload  │
   │  │  · consensus      │  │◄────►│  snap / full sync    │   │  building)       │
   │  └───────────────────┘  │      └──────────────────────┘   └──────────────────┘
   │  ┌───────────────────┐  │
   │  │ core/txpool       │  │      ┌──────────────────────────────────────────┐
   │  │  legacy + blob    │  │      │  eth/protocols (eth, snap) · eth/fetcher  │
   │  └───────────────────┘  │◄────►│  wire protocols over p2p                  │
   └───────────┬─────────────┘      └──────────────────────────────────────────┘
               │ reads/writes
               ▼
   ┌──────────────────────────────────────────────────────────────────────────┐
   │  State & storage: core/state (StateDB) → trie → triedb (hashdb|pathdb)     │
   │  → ethdb (pebble|leveldb) + core/rawdb (schema) + freezer/ancient + era    │
   └──────────────────────────────────────────────────────────────────────────┘
               ▲
               │ transport
   ┌───────────┴──────────────────────────────────────────────────────────────┐
   │  p2p: discover(v4/v5) · enode/enr · rlpx · dnsdisc · nat · netutil          │
   └────────────────────────────────────────────────────────────────────────────┘

2.2 The node service container

node.Node (package node) is the lifecycle and resource container that everything else plugs into. It owns:

  • Datadir and keystore resolution — resolves the data directory, keystore path, and node key; manages the instance directory lock.
  • P2P server — the devp2p p2p.Server that handles discovery and peer connections.
  • The account manager (accounts.Manager) — aggregates keystore, USB, and smartcard backends.
  • The RPC stack — IPC, HTTP, WebSocket, and the separate authenticated (Engine API) server, plus optional GraphQL. Default hosts/ports come from node.DefaultConfig:
Endpoint Default host Default port Default modules
HTTP localhost 8545 net,web3
WebSocket localhost 8546 net,web3
Auth (Engine API) localhost 8551 eth,engine
IPC — (geth.ipc in datadir) — all local

Services register with the node and are started/stopped in dependency order. cmd/geth's makeFullNode wires eth.Ethereum and its satellites into the node.

2.3 The eth execution service

eth.Ethereum (package eth) is the main EL service. It composes:

  • core.BlockChain — the canonical chain, block insertion/validation, the state processor that runs each block through the EVM, and reorg handling.
  • core/vm — the Ethereum Virtual Machine: opcode interpreter, gas accounting, and precompiled contracts.
  • core/txpool — the transaction mempool, split into the legacy pool (legacypool) for normal transactions and blobpool for EIP-4844 blob transactions.
  • eth/downloader — orchestrates snap and full sync.
  • eth/protocols/eth and eth/protocols/snap — the wire protocols spoken to peers; eth/fetcher pulls announced blocks and transactions.
  • eth/filters — log/event filtering backing eth_getLogs and subscriptions, accelerated by core/filtermaps log indexes.
  • eth/gasprice — the gas-price oracle backing fee suggestions.
  • eth/tracers — transaction tracing engines (native Go tracers and JavaScript tracers via goja).
  • miner — block/payload construction, invoked when the CL requests a payload via the Engine API.

eth/ethconfig defines the service's configuration struct and its defaults (sync mode, cache splits, txpool sizing, GPO parameters, RPC caps, history retention).

2.4 Consensus and the Engine API

Geth supports multiple consensus engines behind the consensus.Engine interface:

Package Engine Use
consensus/beacon Beacon (post-merge) Wraps an inner engine; defers fork choice to the CL via the Engine API. The production path for mainnet.
consensus/clique Clique Proof-of-authority, used by --dev and private PoA networks.
consensus/ethash Ethash Legacy proof-of-work verification (historical blocks); not used for live mining.
consensus/misc — Shared fork rules (EIP-1559 base fee, EIP-4844 blob fee).

eth/catalyst implements the Engine API — the engine_forkchoiceUpdated, engine_newPayload, and payload-building methods the CL calls on the authenticated port. beacon/engine defines the shared request/response types. The beacon/ tree also contains a full beacon light client (beacon/light, beacon/blsync) that powers the blsync tool.

2.5 State and storage stack

State storage is layered from high-level abstraction down to bytes on disk:

core/state.StateDB        ← accounts, balances, nonces, code, storage slots
        │
        ▼
trie (Merkle-Patricia)    ← cryptographic state commitment; trie/bintrie = experimental binary trie
        │
        ▼
triedb                    ← node store with two schemes:
        ├─ hashdb         ← legacy: nodes keyed by hash
        └─ pathdb         ← modern default: nodes keyed by path, online pruning, state history
        │
        ▼
ethdb (KV interface)      ← pebble (default) | leveldb | memorydb | remotedb
        │
        ▼
core/rawdb                ← concrete key schema; "ancient"/freezer for immutable old data
        └─ eradb / internal/era  ← Era archive format for historical blocks
  • triedb/pathdb is the largest single module in the codebase and the modern default (--state.scheme path). It supports efficient pruning and bounded state history.
  • triedb/hashdb is the legacy hash-keyed scheme.
  • The freezer (ancient store) moves immutable old blocks out of the hot KV store into append-only flat files (--datadir.ancient), dramatically shrinking the live database.
  • Era files (--datadir.era, geth import-history/export-history/download-era) provide compact, verifiable archives of historical blocks.

2.6 Networking stack (p2p)

Package Responsibility
p2p The peer server, connection lifecycle, protocol multiplexing
p2p/discover Node discovery DHT — protocol v4 and v5
p2p/enode, p2p/enr Node identity and Ethereum Node Records
p2p/rlpx The encrypted RLPx transport
p2p/dnsdisc DNS-based node lists
p2p/nat NAT traversal (UPnP, NAT-PMP, STUN, explicit ext-IP)
p2p/netutil, p2p/msgrate, p2p/tracker IP restriction, peer message-rate estimation, request tracking

core/forkid computes the fork identity used during the handshake so peers only connect to compatible chains.

2.7 Supporting subsystems

Package Role
rpc The JSON-RPC server/client framework (codecs, subscriptions, batching)
internal/ethapi Implementations of the eth/debug-namespace RPC methods
graphql GraphQL schema and resolvers (plus GraphiQL UI)
accounts Account abstraction; keystore, usbwallet, scwallet backends; abi for contract encoding
signer Offline/structured signing helpers (fourbyte selector DB, storage, core types)
ethclient A Go client library for talking to a node (used by tooling and simulated backends)
metrics Instrumentation registry with Prometheus and InfluxDB exporters
log Structured, leveled logging
params Chain configurations, fork schedules, and protocol constants
rlp Recursive Length Prefix serialization
common Hashing, hex, big-int, LRU, and primitive types
ethstats Optional reporting to an ethstats dashboard
internal/debug pprof, the --verbosity/log flags, and the debug runtime namespace

3. System Requirements

Resource Full (pruned) node Archive node
CPU 4+ cores 8+ cores
RAM 16 GB 32 GB+
Disk Terabyte-class NVMe/SSD with headroom Multi-terabyte NVMe
Disk type NVMe/SSD required NVMe required
Network Stable broadband, port 30303 open (TCP+UDP) same

Caution

Mechanical disks (HDD) are not viable for any sync mode. State access during sync and block import is random-IO heavy; an HDD will cause the node to fall permanently behind the chain head. This is the most common cause of "node never syncs" support cases.

Note

Geth auto-shuts-down when free disk falls below --datadir.minfreedisk (MB). Provision generous headroom; chain data grows continuously even on a pruned node.


4. Configuration Mastery

Geth has roughly 250 command-line flags. Every flag has a matching GETH_<NAME> environment variable (via flags.AutoEnvVars), and the full effective configuration can be dumped and reloaded as TOML.

4.1 Configuration precedence and the TOML file

# Dump the effective configuration to TOML
geth dumpconfig --mainnet > geth.toml

# Run with a config file (flags still override individual values)
geth --config geth.toml --mainnet

Precedence (highest wins): explicit CLI flags → environment variables (GETH_*) → --config TOML file → built-in defaults.

Tip

For reproducible production deployments, generate a geth.toml with dumpconfig, commit it to configuration management, and pass --config. Keep only environment-specific values (datadir, JWT path, RPC exposure) as CLI flags.

4.2 Data, database, and history

Flag Default Purpose
--datadir <dir> platform-specific Databases and keystore root
--datadir.ancient <dir> inside chaindata Freezer (ancient) data root
--datadir.era <dir> inside ancient/chain Era1 history root
--datadir.minfreedisk <MB> --cache.gc-derived Free-disk floor before auto-shutdown (0 = disabled)
--keystore <dir> inside datadir Keystore directory
--db.engine <name> pebble Backing KV store: pebble or leveldb
--remotedb <url> — Connect to a remote database
--state.scheme <scheme> path path (modern, prunable) or hash (legacy)
--gcmode <mode> full full (prune state) or archive (retain all)
--history.state <n> 90,000 Blocks of state history to retain (path scheme; 0 = all)
--history.transactions <n> ~1 year Blocks of transaction index (0 = all)
--history.logs <n> ~1 year Blocks of log-search index (0 = all)
--history.logs.disable off Do not maintain a log index
--history.chain <mode> all Body/receipt retention: all, postmerge, postprague

4.3 Sync and cache

Flag Default Purpose
--syncmode <mode> snap snap or full
--snapshot enabled Enable snapshot-database acceleration
--cache <MB> 1024 Total memory for internal caching
--cache.database <pct> — Share of cache for DB IO
--cache.trie <pct> 15% full / 30% archive Share for trie caching
--cache.gc <pct> 25% full / 0% archive Share for trie pruning
--cache.snapshot <pct> 10% full / 20% archive Share for snapshot caching
--cache.noprefetch off Disable heuristic state prefetch
--cache.preimages off Record keccak preimages of trie keys
--fdlimit <n> system limit Raise the open-file-descriptor limit

Tip

On a memory-rich machine, raising --cache (e.g. --cache 8192) materially speeds sync and block import. The percentage sub-flags rebalance how that budget is split; the defaults are sensible for full mode.

4.4 Networking and discovery

Flag Default Purpose
--port <n> 30303 P2P listening port (TCP)
--discovery.port <n> 30303 UDP discovery port
--maxpeers <n> 50 Max peers (0 disables networking)
--maxpendpeers <n> (default) Max pending connection attempts
--bootnodes <enodes> network default Bootstrap enode URLs
--nat <spec> any any|none|upnp|pmp|pmp:<IP>|extip:<IP>|stun:<IP:PORT>
--nodiscover off Disable discovery (manual peers only)
--discovery.v4 / --discovery.v5 on Toggle discovery protocols (aliases discv4/discv5)
--netrestrict <CIDR> — Restrict peers to given IP networks
--discovery.dns <urls> network default DNS discovery entry points ("" to disable)
--nodekey <file> / --nodekeyhex <hex> auto P2P node key
--identity <name> — Custom node name

4.5 RPC, Engine API, and GraphQL

Flag Default Purpose
--http / --http.addr / --http.port off / localhost / 8545 HTTP-RPC server
--http.api <list> net,web3 HTTP namespaces
--http.corsdomain <list> — Allowed CORS origins (browser enforced)
--http.vhosts <list> localhost Allowed virtual hosts (server enforced)
--http.rpcprefix <path> / HTTP path prefix for JSON-RPC
--ws / --ws.addr / --ws.port off / localhost / 8546 WebSocket-RPC server
--ws.api <list> / --ws.origins <list> net,web3 / — WS namespaces / allowed origins
--ipcdisable / --ipcpath <name> enabled / geth.ipc IPC server toggle / socket name
--graphql off GraphQL on the HTTP server
--authrpc.addr / --authrpc.port localhost / 8551 Engine API listener
--authrpc.vhosts <list> localhost Engine API virtual hosts
--authrpc.jwtsecret <file> auto (<datadir>/geth/jwtsecret) JWT secret for the Engine API
--rpc.gascap <n> 50,000,000 Gas cap for eth_call/estimateGas (0 = infinite)
--rpc.txfeecap <ether> 1 Max tx fee via RPC (0 = no cap)
--rpc.evmtimeout <dur> (set) eth_call timeout (0 = infinite)
--rpc.batch-request-limit <n> (set) Max requests per batch
--rpc.batch-response-max-size <n> (set) Max batch response bytes
--rpc.allow-unprotected-txs off Allow non-EIP-155 (unprotected) txs via RPC

Warning

--http.vhosts and --http.corsdomain default to localhost/empty for a reason. Setting either to * removes a layer of protection against DNS-rebinding and cross-origin attacks. Only widen them behind a trusted reverse proxy.

4.6 Transaction pool

Flag Purpose
--txpool.locals <accts> Accounts treated as local (no flush, priority inclusion)
--txpool.nolocals Disable price exemptions for local txs
--txpool.journal <file> / --txpool.rejournal <dur> Local-tx journal and regeneration interval
--txpool.pricelimit <n> Minimum gas-price tip for acceptance
--txpool.pricebump <pct> Replacement price bump
--txpool.accountslots / --txpool.globalslots Executable slot limits per account / global
--txpool.accountqueue / --txpool.globalqueue Non-executable (queued) slot limits
--txpool.lifetime <dur> Max time non-executable txs are queued
--blobpool.datadir / --blobpool.datacap / --blobpool.pricebump Blob-transaction pool storage and sizing

4.7 Block building (miner / payload)

Flag Purpose
--miner.gaslimit <n> Target gas ceiling for built blocks
--miner.gasprice <wei> Minimum gas price to include a transaction
--miner.extradata <str> Block extra-data (default = client version)
--miner.recommit <dur> Interval to rebuild the in-progress block
--miner.maxblobs <n> Max blobs per block
--miner.pending.feeRecipient <addr> Fee recipient for the pending block (not actual production)

Note

On a post-merge network the actual fee recipient for produced blocks is supplied by the CL via the Engine API's payload attributes, not by a Geth flag. The --miner.* flags configure block-building parameters; they do not enable PoW mining.

4.8 Metrics, telemetry, and gas-price oracle

Flag group Purpose
--metrics, --metrics.addr, --metrics.port Enable and serve the metrics HTTP endpoint
--metrics.influxdb* / --metrics.influxdbv2* Push metrics to InfluxDB v1 / v2
--rpc.telemetry* OpenTelemetry tracing for RPC (OTLP endpoint, auth, sample ratio)
--gpo.blocks, --gpo.percentile, --gpo.maxprice, --gpo.ignoreprice Gas-price-oracle tuning
--ethstats <url> Report to an ethstats service (nodename:secret@host:port)

4.9 Fork overrides

Flag Purpose
--override.osaka <ts> Override the bundled Osaka fork timestamp
--override.bpo1 / --override.bpo2 <ts> Override BPO fork timestamps
--override.ubt <ts> Override the UBT (binary-trie) fork timestamp
--override.genesis <file> Load genesis and config from a file

Caution

Fork-override flags are for testing and emergency coordination. Setting an incorrect fork timestamp will fork your node off the canonical chain. Do not use them on a production mainnet node unless following explicit, official guidance.


5. Deployment

5.1 Reference topology

            ┌────────────── host (firewalled) ──────────────┐
   :30303   │  ┌───────────┐  Engine API     ┌────────────┐ │
 ◄── P2P ──►│  │   geth    │◄── :8551 + JWT ──│ CL client  │ │
            │  │  (EL)     │                  │ (beacon)   │◄┼─► :9000 CL P2P
   :8545    │  └─────┬─────┘                  └────────────┘ │
 ◄── RPC ───┼────────┘ (localhost only)                      │
 (proxy)    │  jwt.hex (chmod 600) shared between the two     │
            └─────────────────────────────────────────────────┘

5.2 systemd unit (Geth)

# /etc/systemd/system/geth.service
[Unit]
Description=Go Ethereum (execution layer)
After=network-online.target
Wants=network-online.target

[Service]
User=geth
Group=geth
Type=simple
Restart=on-failure
RestartSec=5
TimeoutStopSec=300
ExecStart=/usr/local/bin/geth \
  --mainnet \
  --datadir /srv/geth \
  --http --http.addr 127.0.0.1 --http.api eth,net,web3 \
  --authrpc.addr localhost --authrpc.port 8551 \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex \
  --metrics --metrics.addr 127.0.0.1
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now geth
journalctl -u geth -f

Important

Set TimeoutStopSec generously (≥ 300s). Geth needs time to flush state on shutdown; a short stop timeout causes systemd to SIGKILL it, leading to a slow state-recovery rewind on the next start.

5.3 JWT secret provisioning

sudo mkdir -p /etc/ethereum
openssl rand -hex 32 | tr -d "\n" | sudo tee /etc/ethereum/jwt.hex >/dev/null
sudo chown geth:geth /etc/ethereum/jwt.hex
sudo chmod 600 /etc/ethereum/jwt.hex

Point both Geth (--authrpc.jwtsecret) and the CL client at this file.

5.4 Docker / Compose

# docker-compose.yml (excerpt)
services:
  geth:
    build: .
    command:
      - --mainnet
      - --datadir=/data
      - --http
      - --http.addr=0.0.0.0
      - --http.api=eth,net,web3
      - --authrpc.addr=0.0.0.0
      - --authrpc.jwtsecret=/jwt/jwt.hex
    volumes:
      - geth-data:/data
      - ./jwt:/jwt:ro
    ports:
      - "127.0.0.1:8545:8545"
      - "30303:30303"
      - "30303:30303/udp"
volumes:
  geth-data:

Warning

Inside containers you must bind --http.addr 0.0.0.0 so the port is reachable, but publish it to 127.0.0.1 on the host (as above) — never 0.0.0.0:8545:8545 on a public host.

5.5 Deployment checklist

  • [ ] Chain data on NVMe/SSD with terabyte-class headroom
  • [ ] LimitNOFILE/--fdlimit raised (≥ 65536)
  • [ ] JWT secret generated, chmod 600, shared with the CL client
  • [ ] RPC bound to localhost (or behind a reverse proxy with auth)
  • [ ] Only required namespaces in --http.api; admin/debug not public
  • [ ] P2P port 30303 open (TCP and UDP); NAT configured if applicable
  • [ ] Metrics endpoint scraped; alerts on sync status, peer count, head age
  • [ ] Consensus client running and authenticated
  • [ ] Graceful-shutdown timeout (TimeoutStopSec) ≥ 300s
  • [ ] Backup of keystore and jwt.hex stored securely off-host

6. Security

6.1 Threat model and surfaces

Surface Risk Mitigation
JSON-RPC (HTTP/WS) Data exfiltration, tx submission, DoS Bind localhost; restrict namespaces; vhosts/corsdomain; reverse proxy with auth/TLS
admin/debug namespaces Peer manipulation, resource-heavy traces Never expose publicly; IPC-only
Engine API (8551) Unauthorized fork-choice control JWT secret (chmod 600); bind localhost
Keystore Key theft → loss of funds File permissions; offline backup; strong passwords; hardware wallets
P2P Eclipse/DoS --netrestrict, trusted peers, adequate --maxpeers
Unprotected txs Replay across chains Keep --rpc.allow-unprotected-txs off

6.2 Hardening rules

Caution

Apply all of the following on any internet-connected node:

  1. Default-deny RPC exposure. Keep --http.addr/--ws.addr on localhost. If remote access is required, terminate TLS and authentication at a reverse proxy; never expose Geth's raw RPC port to the internet.
  2. Minimize namespaces. Expose only eth,net,web3 over HTTP/WS. admin, debug, and txpool belong on the IPC socket.
  3. Lock the vhost/CORS gates. Leave --http.vhosts/--http.corsdomain at their restrictive defaults unless a proxy requires otherwise. Avoid *.
  4. Protect the JWT secret. chmod 600, owned by the service user. It is the credential that lets the CL drive your node.
  5. Treat the keystore as cash. Back it up offline; the password is not stored in the file. Use --lightkdf only on test networks.
  6. Run as a non-root user with a dedicated datadir and minimal filesystem permissions.

6.3 Removed legacy surface (negative knowledge)

Note

The legacy personal RPC namespace (remote account unlock/sign over RPC) has been removed from Geth and is not available. Do not design integrations around personal_unlockAccount or personal_sendTransaction. Use an external signer (--signer), hardware wallets, or offline key management (ethkey) instead. This repository also does not ship the clef signer binary or a standalone bootnode binary — discovery/bootnode duties are covered by the devp2p tool.

6.4 Malicious-input resistance

Geth includes an extensive fuzzing suite (tests/fuzzers: bls12381, bn256, rangeproof, secp256k1, txfetcher, difficulty) and documented post-mortems (docs/postmortems) and security audits (docs/audits). Consensus-critical code paths (EVM, trie, crypto, RLP) are the primary fuzz targets. Operators should track upstream security advisories and apply patch releases promptly, as a consensus bug can fork a node off the network.


7. Operations

7.1 Start, stop, status

sudo systemctl start geth
sudo systemctl stop geth          # graceful; allow up to TimeoutStopSec
sudo systemctl status geth
journalctl -u geth -f             # follow logs

Health check from a console:

geth attach --exec 'eth.syncing'        # false when synced
geth attach --exec 'net.peerCount'      # healthy peer count
geth attach --exec 'eth.blockNumber'    # head should advance ~every 12s

7.2 Logging

Verbosity is controlled by the debug flag group: --verbosity <0-5> (0=silent, 3=info default, 5=trace). --log.format, --log.file, and pprof flags are available for structured output and profiling. The internal/debug package also exposes a runtime debug RPC namespace and an embedded pprof server.

7.3 Backup and restore

Asset Backup method Notes
Keystore Copy <datadir>/keystore Portable; passwords stored separately
JWT secret Copy /etc/ethereum/jwt.hex Regenerate + restart both clients if rotated
Chain data Snapshot the volume while Geth is stopped Or simply re-sync; chain data is reproducible
Era archives Copy --datadir.era / export with export-history Verifiable against accumulator roots

Tip

Chain and state data are fully reproducible from the network, so the only irreplaceable assets are the keystore and (for coordination) the JWT secret. Prioritize those in backup policy; treat chain data as a cache that can be rebuilt by re-syncing.

7.4 Database maintenance

# Stop geth first for most of these
geth snapshot verify-state          # integrity check of state vs. snapshot
geth db check-state-content         # verify state is cryptographically correct
geth db metadata                    # inspect database metadata
geth prune-history                  # reclaim space from old bodies/receipts
geth removedb                       # nuke chain/state (keeps keystore) → re-sync

Warning

geth db delete/geth db put perform raw key mutations and can corrupt the database — the help text says so explicitly. Use them only when you understand the exact key schema in core/rawdb.

7.5 Upgrades

sudo systemctl stop geth
# build/install the new geth binary
geth version                        # confirm the new build
sudo systemctl start geth
journalctl -u geth -f               # watch for migration/recovery messages

Important

Read the release notes before upgrading across a network fork. Some releases change the state scheme, require a database migration, or carry a hard-fork activation. Upgrade the CL client and Geth in the order the release notes specify, and never skip a fork-activating release on mainnet.

7.6 Incident playbook

Symptom First checks Action
Head not advancing Is the CL running and authenticated? eth.syncing? Restart CL; verify JWT; check Engine API logs
Falling behind Disk type/IO, peer count, CPU Move to NVMe; raise --cache; check peers
Crash-loop on start State recovery / corrupt DB messages Allow recovery; if corrupt, removedb + re-sync
Out of disk df; --datadir.minfreedisk triggered Free/extend volume; enable history pruning
No peers Firewall, NAT, bootnodes Open 30303 TCP+UDP; set --nat; check --bootnodes
RPC unreachable Was --http set? Right addr/vhosts? Enable transport; check bind address and namespaces

8. Repository Structure (Developer Reference)

The codebase is organized by subsystem. Top-level packages and their roles:

Path Role
cmd/geth The geth binary: CLI app, subcommands, node assembly
cmd/utils Shared flag definitions and node/config builders (the config surface)
cmd/{abigen,evm,devp2p,ethkey,era,rlpdump,abidump,blsync,workload,fetchpayload} Companion tools
node Service container, RPC stack, lifecycle
eth The execution-layer service; eth/ethconfig holds its config
eth/downloader Snap/full sync engine
eth/protocols/{eth,snap} Wire protocols
eth/fetcher Block/transaction fetching
eth/filters Log/event filtering (eth_getLogs, subscriptions)
eth/gasprice Gas-price oracle
eth/tracers Native + JS transaction tracers
eth/catalyst Engine API implementation
core Blockchain, genesis, state processor
core/vm The EVM
core/state StateDB and state objects
core/txpool (legacypool, blobpool) Transaction mempool
core/rawdb Low-level DB schema + freezer
core/filtermaps Log index
core/tracing Tracing hooks
core/forkid Fork identity
consensus/{beacon,clique,ethash,misc} Consensus engines and fork rules
trie, trie/bintrie, trie/trienode State trie (MPT + experimental binary trie)
triedb, triedb/{pathdb,hashdb} Trie node store schemes
ethdb (pebble, leveldb, memorydb, remotedb) KV database abstraction
p2p (discover, enode, enr, rlpx, dnsdisc, nat, netutil) Networking stack
accounts (keystore, usbwallet, scwallet, abi) Account management
signer (fourbyte, core, storage) Signing helpers
rpc JSON-RPC framework
internal/ethapi RPC method implementations
graphql GraphQL API
miner Block/payload building
beacon (light, blsync, engine, params, merkle) Beacon light client + Engine types
metrics, log, params, rlp, common Cross-cutting infrastructure
ethclient Go client library
internal/era, core/rawdb/eradb Era archive format
ethstats ethstats reporting

8.1 Building and testing

make geth          # build the geth binary
make all           # build all binaries
go test ./...      # run the full test suite
go test ./core/... # subsystem-scoped tests

The repository uses code generation (go:generate with gencodec, stringer, protoc-gen-go; see the tool directive in go.mod) and rlp/rlpgen for RLP codecs. Regenerate generated code rather than hand-editing it.

8.2 Contributing

Contributions follow upstream Go conventions: gofmt-clean code, focused commits, and full test coverage for consensus-critical changes. Consensus-affecting code (EVM, trie, crypto, RLP, fork rules) carries the highest review bar because a divergence forks nodes off the network. The fuzzing harnesses in tests/fuzzers should be extended alongside changes to parsing or cryptographic code paths.


9. Internals Deep Dive: Request and Block Lifecycles

9.1 Inbound block (from a peer)

  1. A peer announces a block via the eth protocol; eth/fetcher requests the body.
  2. core.BlockChain validates the header (consensus engine) and re-executes transactions through core/vm, mutating a core/state.StateDB.
  3. The resulting state trie is committed via trie → triedb → ethdb; immutable old data eventually migrates to the freezer.
  4. If the block extends the canonical chain (per CL fork choice), the head advances; otherwise a reorg is evaluated.

9.2 Engine API payload (from the CL)

  1. The CL calls engine_forkchoiceUpdated with payload attributes (incl. fee recipient) on the authenticated port.
  2. eth/catalyst instructs miner to build a payload: pull transactions from core/txpool, execute them, and assemble a block.
  3. The CL retrieves the payload, and after consensus, calls engine_newPayload to commit it; Geth validates and imports it as in §9.1.

9.3 JSON-RPC call (eth_call)

  1. The rpc server decodes the request and routes it to the eth namespace handler in internal/ethapi.
  2. The handler snapshots state at the requested block, runs the call through core/vm under the --rpc.gascap and --rpc.evmtimeout limits, and returns the result without mutating state.

9.4 Sync (snap)

  1. eth/downloader selects a pivot and requests account/storage ranges via eth/protocols/snap.
  2. State is reconstructed into triedb; block bodies are backfilled.
  3. Once the pivot is reached, the node switches to full validation and follows the head under CL fork choice.

10. Improvements and Technical Notes

Observations relevant to operators and maintainers, derived from the source structure:

  1. State-scheme migration friction. Switching between path and hash schemes (or full ↔ archive) is not a live toggle and generally requires a re-sync. Operators should choose deliberately at first sync; documentation and tooling that make the migration path clearer would reduce a common operational pitfall.
  2. Binary trie is in flight. trie/bintrie, the geth bintrie convert command, and the --override.ubt fork flag indicate an in-progress migration toward a binary state trie. Treat bintrie features as experimental and not for production state.
  3. Two-client coordination is the dominant failure mode. The majority of "node won't sync" situations reduce to a missing/misauthenticated CL client. Surfacing Engine-API connectivity prominently in health output and logs continues to pay off.
  4. Large modules. triedb/pathdb, core, core/rawdb, trie, and core/state are the largest and most consensus-critical modules; changes there warrant the deepest review and fuzzing.
  5. Open upstream issues to track (from the community issue tracker at analysis time): a reported freezer error (canonical hash missing, can't freeze block) and an external-signer EIP-7702 authorization-list handling issue. Operators relying on freezer pruning or external signers with set-code (EIP-7702) transactions should monitor these.
  6. Config reproducibility. The dumpconfig/--config TOML round-trip plus GETH_* env vars make Geth well-suited to declarative configuration management; standardizing on a committed geth.toml reduces drift across a fleet.

11. Quick Reference

11.1 Default ports

Service Port Protocol
P2P (discovery + transport) 30303 TCP + UDP
HTTP-RPC 8545 TCP
WebSocket-RPC 8546 TCP
Engine API (auth) 8551 TCP
Metrics (when enabled) 6060 TCP

11.2 Default RPC modules

Endpoint Default modules
HTTP net,web3
WebSocket net,web3
Auth (Engine API) eth,engine
IPC / console all local namespaces

11.3 Essential operations

Task Command
Build make geth
Dump config geth dumpconfig --mainnet > geth.toml
Attach console geth attach
Check sync geth attach --exec 'eth.syncing'
Reset DB (keep keys) geth removedb
Verify state geth snapshot verify-state
Export/import chain geth export <file> / geth import <file>
Init custom genesis geth --datadir <dir> init genesis.json

11.4 Key file locations

Path Contents
<datadir>/keystore Encrypted account keys
<datadir>/geth/chaindata Chain and state database
<datadir>/geth/jwtsecret Auto-generated Engine API JWT (if not overridden)
<datadir>/geth.ipc IPC socket
--datadir.ancient Freezer (frozen old blocks)
--datadir.era Era history archives