How to Run Your Own BNB Smart Chain (BSC) Node
A BNB Smart Chain node is a single client — bnb-chain/bsc, a fork of Geth — so it’s simpler to run than a post-Merge Ethereum node (no separate consensus client). It gives you a private endpoint on chain ID 56 with no rate limits. The one thing that defines the BSC experience: the chain is huge and grows fast(3-second blocks, high throughput, 40M+ blocks), so you don’t sync from genesis — you bootstrap from a snapshot. This guide is the official setup on Ubuntu 24.04.
Hardware requirements
BSC publishes two practical tiers. A fast node keeps the latest world state in a lighter footprint (what most people running their own RPC want); a full nodekeeps more history and needs more disk. Both want a fast NVMe SSD — BSC’s throughput makes disk I/O the bottleneck.
| Resource | Fast node | Notes |
|---|---|---|
| CPU | 16 cores | High single-thread performance helps. |
| RAM | 32 GB+ | |
| Disk | 2 TB+ NVMe SSD | gp3-class: ~8k IOPS, 250 MB/s, read latency <1ms. Snap sync needs NVMe. State grows continuously — leave headroom. |
| Network | Stable, 5 MB/s+ | More is better; snapshot download is hundreds of GB. |
Because BSC is a Geth fork, the client mechanics (snap vs full sync, path-based state, pruning) will feel familiar if you’ve read Geth vs Erigon vs Reth. Want the full transaction history and old state? That’s an archive node— dramatically more disk; most people don’t need it.
Step 1 — Download the geth binary and mainnet config
Grab the pre-built binary and the mainnet config bundle (genesis.json + config.toml) from the latest bnb-chain/bsc release:
# the geth binary wget $(curl -s https://api.github.com/repos/bnb-chain/bsc/releases/latest \ | grep browser_ | grep geth_linux | cut -d'"' -f4) mv geth_linux geth && chmod +x geth # mainnet genesis.json + config.toml wget $(curl -s https://api.github.com/repos/bnb-chain/bsc/releases/latest \ | grep browser_ | grep mainnet | cut -d'"' -f4) unzip mainnet.zip # -> genesis.json, config.toml
Step 2 — Bootstrap from a snapshot (don’t sync from genesis)
Syncing BSC from block 0 would take an impractically long time. Instead, download a recent chaindata snapshot and drop it into your data directory. Snapshots are published at bnb-chain/bsc-snapshots:
sudo mkdir -p /data/bsc # Follow the current instructions on the bsc-snapshots repo to fetch the latest # snapshot (it changes constantly). Extract its "geth" chaindata under: # /data/bsc/geth/chaindata # The snapshot IS the initialized chaindata — no separate 'geth init' needed.
Snapshots are large (hundreds of GB) and go stale quickly; once restored, the node only needs to catch up the blocks produced since the snapshot was taken.
Step 3 — Dedicated user and systemd service
Run as an unprivileged bsc user and manage the process with systemd. Create /etc/systemd/system/bsc.service (the start command matches the official recommendation):
sudo useradd --system --no-create-home --shell /usr/sbin/nologin bsc sudo mkdir -p /data/bsc && sudo chown -R bsc:bsc /data/bsc /opt/bsc # put geth, config.toml, genesis.json under /opt/bsc sudo tee /etc/systemd/system/bsc.service >/dev/null <<'EOF' [Unit] Description=BNB Smart Chain Full Node After=network-online.target Wants=network-online.target [Service] User=bsc WorkingDirectory=/opt/bsc ExecStart=/opt/bsc/geth \ --config /opt/bsc/config.toml \ --datadir /data/bsc \ --syncmode snap \ --cache 10000 \ --rpc.allow-unprotected-txs \ --history.transactions 0 \ --history.logs 576000 Restart=always RestartSec=5 LimitNOFILE=200000 [Install] WantedBy=multi-user.target EOF
--cache 10000 gives the DB plenty of memory; --history.transactions 0 and --history.logs 576000 keep the node lighter by trimming old history (raise or remove these if you need deeper lookups). Edit config.toml to enable the HTTP/WS RPC on 127.0.0.1and expose only the namespaces you need — then firewall it.
Step 4 — Start and verify
sudo systemctl daemon-reload
sudo systemctl enable --now bsc
# watch it import blocks
tail -f /data/bsc/bsc.log # look for "Imported new chain segment"
# once RPC is up, confirm chain ID 56 (0x38)
curl http://localhost:8545 -s -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
# -> {"jsonrpc":"2.0","id":1,"result":"0x38"}Don’t trust “it responds” as “it’s synced” — confirm the head is actually at the tip and advancing using the checks in Is your RPC node actually at the chain tip?.
The honest part: what running it actually costs
BSC is deceptively simple to start and genuinely demanding to keep running:
- The disk never stops growing. Fast blocks and high volume mean state and history expand continuously; a node that fit last quarter can fill its disk this quarter. You’ll be managing storage forever.
- Snapshots are a recurring chore. Bootstrapping and (after any corruption or fresh start) re-bootstrapping means downloading hundreds of GB and babysitting the restore. High-IOPS NVMe isn’t optional.
- Hard forks need prompt upgrades. BSC ships frequent client releases with scheduled fork blocks; miss one and your node stops following the chain.
- One node is a single point of failure. Production use wants at least two, plus a load balancer and health checks — doubling all of the above. See Self-Hosted Node vs RPC Provider.
…or skip all of it
SwiftNodes runs load-balanced BNB Smart Chain nodes for you — flat-rate pricing (no per-call compute units), HTTP + WebSocket, no KYC — alongside 75+ other chains under one API key. No snapshot babysitting, no disk-space firefighting.
Grab a key at swiftnodes.io and point your app at https://rpc.swiftnodes.io/rpc/bsc?key=YOUR_API_KEY.