Coinbase's Base L2 runs on Go. Here's how to run your own node and what it teaches you about Go infrastructure.
· 3 min read

Did you know you can run your own Base node with Go?


Whatever you make of crypto, the infrastructure underneath it is an interesting place to watch Go work hard. Base is Coinbase’s Layer 2 blockchain built on the OP Stack, the whole stack is written in Go, and the base/node project gives you everything you need to run a node of your own. It makes a surprisingly good weekend project.

What is Base node?

Base is an Ethereum Layer 2 (L2) network. It processes transactions off the main Ethereum chain, then posts them back in batches, which makes transactions faster and cheaper.

The base/node repository contains the Docker configuration and scripts for running your own node. Under the hood there are two main components: op-node, the consensus client from the OP Stack, and op-geth, a modified version of go-ethereum (geth).

Both are written in Go, and that’s no accident. Go took over blockchain infrastructure early because of its performance and concurrency support, and it never let go. If you’re curious about the concurrency side, check out how goroutines work under the hood.

Getting started

First, clone the repository:

git clone https://github.com/base-org/node.git
cd node

The project uses Docker Compose. You’ll need to configure your environment:

# Copy the example environment file
cp .env.example .env

Edit the .env file with your settings:

# Your L1 Ethereum RPC endpoint (Alchemy, Infura, or your own node)
OP_NODE_L1_ETH_RPC=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY

# Network to connect to (mainnet or sepolia)
NETWORK_ENV=.env.mainnet

Then start your node:

docker compose up -d

Understanding the architecture

The base/node setup runs two containers, and the split between them is worth understanding.

The consensus layer (op-node) connects to L1 Ethereum and works out what the canonical chain should be. The execution layer processes transactions and maintains state; depending on your configuration that may be reth, geth, or Nethermind.

Once it’s up, talking to your node from Go is pleasingly ordinary:

package main

import (
	"context"
	"fmt"
	"log"
	"math/big"

	"github.com/ethereum/go-ethereum/ethclient"
)

func main() {
	// Connect to your local Base node
	client, err := ethclient.Dial("http://localhost:8545")
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// Get the latest block number
	blockNumber, err := client.BlockNumber(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Current block: %d\n", blockNumber)

	// Get chain ID to verify we're on Base
	chainID, err := client.ChainID(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	
	// Base mainnet is chain ID 8453
	if chainID.Cmp(big.NewInt(8453)) == 0 {
		fmt.Println("Connected to Base mainnet!")
	}
}

Monitoring your node

Once it’s running, the first thing you’ll care about is sync status. Here’s a Go function to check it:

func checkSyncStatus(client *ethclient.Client) error {
	ctx := context.Background()
	
	progress, err := client.SyncProgress(ctx)
	if err != nil {
		return err
	}
	
	if progress == nil {
		fmt.Println("Node is fully synced")
		return nil
	}
	
	percentage := float64(progress.CurrentBlock) / float64(progress.HighestBlock) * 100
	fmt.Printf("Syncing: %.2f%% (block %d of %d)\n", 
		percentage, 
		progress.CurrentBlock, 
		progress.HighestBlock)
	
	return nil
}

Be warned: the initial sync takes a long time. Base mainnet has millions of blocks, so start it, walk away, and check back tomorrow rather than staring at the percentage.

Why run your own node?

The honest answer is partly “because you can”. But there are practical reasons too. Your queries stop flowing through third-party RPC providers, which matters if you care about privacy. You’re no longer at the mercy of a public endpoint’s rate limits or outages. And local queries are simply faster.

If you go on to build applications against your node, you’ll be juggling request-scoped timeouts and cancellation constantly, so it’s worth understanding Go’s context package properly before you start.

Hardware requirements

Here’s the catch. Running a full node needs proper hardware: 32GB RAM minimum (64GB recommended by the Base node README), a 1TB SSD (NVMe preferred), and a stable internet connection. The Go runtime is reasonably frugal, but blockchain nodes are memory-hungry beasts in any language.

Wrapping up

You don’t need to become a blockchain developer for this to be worthwhile. Running a node shows you first-hand how an L2 fits together, and watching op-node and the execution client talk to each other is a decent distributed systems lesson on its own.

Start with the base/node repository and the official Base documentation, point your first attempt at Sepolia rather than mainnet, and give the sync a day or two before judging it. Happy syncing.