Derivation Paths (BIP44/49/84/86)
You’ve seen that one seed grows into an unlimited tree of keys via HD wallets (BIP32). But a tree with infinite branches is useless if two wallets disagree on which branches hold your money. Derivation paths are the shared map: a standardized route through the tree so that any compatible wallet, given your seed, lands on the exact same addresses. Get the path wrong and your coins look “missing” — they’re not lost, they’re just down a branch your wallet never checks.
The path structure (BIP44)
Section titled “The path structure (BIP44)”A derivation path is a sequence of steps down the key tree, written like a filesystem path:
m / purpose' / coin_type' / account' / change / address_index│ │ │ │ │ │root what kind which sub- receive(0) the Nth key of wallet coin wallet or in this branch (BTC=0) (0,1,2…) change(1)The apostrophe ' marks a hardened step (see HD wallets for why
hardening protects you if an xpub leaks). A concrete example:
m/84'/0'/0'/0/5 → the 6th (index 5) receive address of the first account of a native-SegWit Bitcoin walletpurpose selects the address type
Section titled “purpose selects the address type”This is the field that trips people up. The purpose number isn’t decorative — by convention it tells the wallet which script type (and therefore which address format) to use. The four you’ll meet:
purpose' | BIP | Script type | Address looks like |
|---|---|---|---|
44' | BIP44 | Legacy P2PKH | 1... |
49' | BIP49 | P2SH-wrapped SegWit | 3... |
84' | BIP84 | Native SegWit (P2WPKH) | bc1q... |
86' | BIP86 | Taproot (P2TR) | bc1p... |
So m/44'/0'/0' and m/84'/0'/0' derived from the same seed produce completely different
addresses — same money-generating secret, different doors. (For what these script types actually
are, see address types and Taproot.)
account, change, and index
Section titled “account, change, and index”account'lets one seed hold independent sub-wallets — “Savings” (0'), “Spending” (1'), “Business” (2') — that don’t share addresses, all recoverable from the one backup.changeis a clever split: branch0is for receive addresses you hand out; branch1is for change addresses your wallet generates internally when a transaction returns leftover funds (see fees & change). Keeping change on its own branch helps the wallet track which addresses are “yours but internal.”address_indexjust counts up:0, 1, 2, …— a fresh address every time, which is exactly the privacy practice you want (never reuse addresses; see privacy & deanonymization).
m/84'/0'/0'/0/0 first receive address (give this out)m/84'/0'/0'/0/1 second receive addressm/84'/0'/0'/1/0 first change address (wallet uses internally)The gap limit
Section titled “The gap limit”Wallets don’t scan infinitely. They look ahead a fixed number of unused addresses — the gap limit, conventionally 20. If you generate address index 0, then jump to index 50 manually, a restoring wallet may stop after 20 empty addresses and never find index 50’s coins. Stay within the gap and your wallet rediscovers everything from the seed alone.
The architect’s lens
Section titled “The architect’s lens”Step back from the slashes and apostrophes and ask the five questions that turn an implementer into an architect:
- Why does it exist? To give the infinite BIP32 tree a shared map —
m / purpose' / coin_type' / account' / change / address_index— so any compatible wallet, handed the same seed, walks to the exact same addresses. - What problem does it solve? Wallet portability without trust. The
purpose'field (44/49/84/86) pins the script type,coin_type'follows the SLIP-0044 registry (BTC =0'), and thechangebranch separates receive (0) from internal change (1) — turning “where are my coins” from guesswork into a deterministic lookup. - What are the trade-offs? The standard is a convention, not enforced by consensus, so a wallet defaulting to the wrong
purpose'shows a zero balance even though the keys are fine — the classic “my coins disappeared” scare. The gap limit (conventionally 20) adds another footgun: skip ahead to index 50 and a restoring wallet may stop scanning before it ever finds those coins. - When is this the wrong design? For a throwaway single-key wallet that never needs portability or sub-accounts, the full five-level path is ceremony you don’t need. And if you stray from registered numbers or invent a private path, you sacrifice the one thing it buys — interoperable recovery in other software.
- What breaks if I remove it? Two wallets sharing a seed would disagree on which branches hold money, so funds would appear “missing” on restore; without the
account'/changestructure you lose independent sub-wallets and the change-address hygiene that keeps internal outputs sorted.
The thread
Section titled “The thread”How do derivation paths help untrusting strangers agree on one ledger? They’re a public standard that makes self-custody portable and verifiable without trusting your wallet vendor. Because the path-to-address mapping is open and deterministic, you can walk away from any wallet app, hand your seed to a different implementation, and it will independently rederive the very same keys — proving your coins were never hostage to one company’s software. Open standards are what keep “be your own bank” from meaning “trust one bank’s app forever.”
Check your understanding
Section titled “Check your understanding”- Write out the six components of a BIP44-style path and say what each one selects.
- Why do
m/44'/0'/0'andm/84'/0'/0'from the same seed produce different addresses? - A user restores their seed and sees a zero balance. What’s the most likely cause, and what’s the fix?
- What is the
changebranch (1) used for, and why keep it separate from the receive branch (0)? - Explain the gap limit and a scenario where ignoring it makes funds appear lost.
Show answers
m / purpose' / coin_type' / account' / change / address_index: m is the root; purpose’ selects the wallet/script type; coin_type’ picks the coin (BTC = 0); account’ the sub-wallet; change chooses receive (0) vs change (1); address_index the Nth key in that branch.- The purpose number selects the script type by convention —
44'is legacy P2PKH,84'is native SegWit — som/44'/0'/0'andm/84'/0'/0'derive different address formats (1...vsbc1q...) from the same seed. Same money-generating secret, different doors. - The most likely cause is restoring into a wallet that defaults to a different
purpose'(derivation path) than the one that received the funds — so it scans the wrong script type and shows zero. The keys are fine; the fix is to restore with the same wallet type / derivation path, or import the correct account descriptor. - Branch
1holds change addresses the wallet generates internally when a transaction returns leftover funds (see fees & change). Keeping it separate from the receive branch (0, the addresses you hand out) helps the wallet track which addresses are “yours but internal.” - The gap limit (conventionally 20) is how many consecutive unused addresses a restoring wallet scans ahead before stopping. If you generate index 0 then jump to index 50 manually, the restore may stop after 20 empty addresses and never find index 50’s coins — they look lost though the key is in your seed. Stay within the gap (or bump it and rescan) and everything reappears.