Core Components
Deep dive into AvalancheGo's package structure, startup flow, and how components interact.
This page provides a detailed overview of AvalancheGo's internal architecture, including the main packages, startup sequence, and how components communicate.
Package Structure
AvalancheGo is organized into well-defined packages, each responsible for specific functionality (top-level folders only):
avalanchego/
├── main/ # CLI entry point
├── app/ # Process lifecycle (signals, shutdown)
├── config/ # Flags/env/config parsing
├── node/ # Node wiring and initialization
├── chains/ # Chain manager and handlers
├── snow/ # Consensus protocols and engines
├── vms/ # Built-in VMs, proposerVM, rpcchainvm
├── network/ # P2P stack
├── message/ # Message codecs
├── database/ # LevelDB/Pebble/memdb backends
├── graft/ # Grafted Coreth (C-Chain EVM)
├── subnets/ # Subnet configs and validator utilities
├── staking/ # TLS/BLS staking keys and POP
├── upgrade/ # Network upgrade rules
├── trace/ # OpenTelemetry tracing helpers
├── utils/ # Common utilities
└── genesis/ # Genesis configuration and samplesStartup Flow
When you run AvalancheGo, the following initialization sequence occurs:
1. Configuration Parsing
func main() {
evm.RegisterAllLibEVMExtras()
// Build configuration from flags/env/config file
fs := config.BuildFlagSet()
v, err := config.BuildViper(fs, os.Args[1:])
if errors.Is(err, pflag.ErrHelp) {
os.Exit(0)
}
if v.GetBool(config.VersionJSONKey) && v.GetBool(config.VersionKey) {
fmt.Println("can't print both JSON and human readable versions")
os.Exit(1)
}
if v.GetBool(config.VersionJSONKey) {
versions := version.GetVersions()
jsonBytes, err := json.MarshalIndent(versions, "", " ")
if err != nil {
fmt.Printf("couldn't marshal versions: %s\n", err)
os.Exit(1)
}
fmt.Println(string(jsonBytes))
os.Exit(0)
}
if v.GetBool(config.VersionKey) {
fmt.Println(version.GetVersions().String())
os.Exit(0)
}
nodeConfig, err := config.GetNodeConfig(v)
if term.IsTerminal(int(os.Stdout.Fd())) {
fmt.Println(app.Header)
}
nodeApp, err := app.New(nodeConfig)
exitCode := app.Run(nodeApp)
os.Exit(exitCode)
}The configuration system supports:
- Command-line flags:
--network-id=fuji,--http-port=9650 - Config file: Pass
--config-file=/path/to/file. The installer writes~/.avalanchego/configs/node.json; source builds do not create a default file. - Environment variables: Prefixed with
AVAGO_
2. Node Initialization
The Node struct in node/node.go orchestrates all components:
type Node struct {
Log logging.Logger
ID ids.NodeID
Config *node.Config
// Networking & routing
Net network.Network
chainRouter router.Router
msgCreator message.Creator
// Storage & shared state
DB database.Database
sharedMemory *atomic.Memory
// VM/chain orchestration
VMAliaser ids.Aliaser
VMManager vms.Manager
VMRegistry registry.VMRegistry
chainManager chains.Manager
// APIs and services
APIServer server.Server
health health.Health
resourceManager resource.Manager
}3. Component Initialization Order
Components are initialized in a specific order to satisfy dependencies:
| Order | Component | Purpose |
|---|---|---|
| 1 | Identity & logging | Staking certs/POP, VM aliases, log factories |
| 2 | Metrics | Prometheus registries + /ext/metrics |
| 3 | APIs | HTTP server + metrics API (health/info/admin added later) |
| 4 | Database & shared memory | Open LevelDB/PebbleDB/memdb and atomic memory |
| 5 | Message codec | message.Creator shared by network/engines |
| 6 | Validators & resources | Validator manager, CPU/disk targeters, resource manager |
| 7 | Networking | Listener, NAT/port mapping, throttlers, IP updater |
| 8 | Health & aliases | Health API, default VM/API/chain aliases |
| 9 | Chain manager & VM registry | Chain manager, register PlatformVM/AVM/EVM + plugins |
| 10 | Indexer & profiler | Optional index API and continuous profiler |
| 11 | Chains | Start PlatformVM, then other chains/bootstrap |
The Node Struct
The Node struct is the central coordinator. Here are its key responsibilities:
VM Management
// Register built-in VMs
n.VMManager.RegisterFactory(ctx, constants.PlatformVMID, &platformvm.Factory{})
n.VMManager.RegisterFactory(ctx, constants.AVMID, &avm.Factory{})
n.VMManager.RegisterFactory(ctx, constants.EVMID, &coreth.Factory{})Chain Creation
When a new chain needs to be created (e.g., during P-Chain bootstrap):
type ChainParameters struct {
ID ids.ID // Chain ID
SubnetID ids.ID // Subnet that validates this chain
GenesisData []byte // Genesis state
VMID ids.ID // Which VM to run
FxIDs []ids.ID // Feature extensions
CustomBeacons validators.Manager // Optional: bootstrap peers for P-Chain
}API Registration
Each VM can register its own API endpoints:
// VM implements CreateHandlers
func (vm *VM) CreateHandlers(ctx context.Context) (map[string]http.Handler, error) {
return map[string]http.Handler{
"/rpc": vm.rpcHandler,
"/ws": vm.wsHandler,
}, nil
}Chain Manager
The Chain Manager (chains/manager.go) is responsible for:
- Creating chains when requested by the P-Chain
- Managing chain lifecycle (start, stop, restart)
- Handling bootstrapping and state sync
- Routing messages between chains and the network
type Manager interface {
// Queue a chain to be created after P-Chain bootstraps
QueueChainCreation(ChainParameters)
// Check if a chain has finished bootstrapping
IsBootstrapped(ids.ID) bool
// Resolve chain aliases
Lookup(string) (ids.ID, error)
// Start the chain creation process
StartChainCreator(platformChain ChainParameters) error
}Chain Bootstrapping
When a chain starts, it progresses through several states to catch up with the network:
Database Layer
AvalancheGo supports multiple database backends:
Database Backends
| Backend | Description |
|---|---|
| LevelDB | Default, widely tested |
| PebbleDB | Modern alternative, better performance |
| memdb | In-memory (non-persistent), useful for fast testing |
Database Organization
Data is organized using prefix databases:
// Each component gets its own namespace
vmDB := prefixdb.New(VMDBPrefix, db)
chainDB := prefixdb.New(chainID[:], vmDB)This allows:
- Isolation: Each VM and chain has isolated storage
- Metrics: Per-database metrics via
meterdb - Cleanup: Easy removal of chain data
Message Flow
Here's how a transaction flows through the system:
Health Checks
AvalancheGo exposes health checks at /ext/health:
type Checker interface {
// HealthCheck returns nil if healthy
HealthCheck(context.Context) (interface{}, error)
}Components that implement health checks:
- Network: Peer connectivity
- Chains: Bootstrap status
- Database: I/O health
- Consensus: Liveness
Metrics
Prometheus metrics are exposed at /ext/metrics:
// Example metrics namespaces
const (
networkNamespace = "avalanche_network"
dbNamespace = "avalanche_db"
consensusNS = "avalanche_snowman"
)Key metrics include:
avalanche_network_peers: Connected peer countavalanche_db_*: Database operationsavalanche_snowman_*: Consensus metricsavalanche_api_*: API request metrics
Next Steps
Is this guide helpful?