docs/add-code-flow.md
ipfs add WorksThis document explains what happens when you run ipfs add to import files into IPFS. Understanding this flow helps when debugging, optimizing imports, or building applications on top of IPFS.
When you add a file to IPFS, three main things happen:
The result is a Content Identifier (CID) - a hash that uniquely identifies your content and can be used to retrieve it from anywhere in the IPFS network.
flowchart LR
A["Your File
(bytes)"] --> B["Chunker
(split data)"]
B --> C["DAG Builder
(tree)"]
C --> D["CID
(hash)"]
# Add a simple file
echo "Hello World" > hello.txt
ipfs add hello.txt
# added QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u hello.txt
# See what's inside
ipfs cat QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u
# Hello World
# View the DAG structure
ipfs dag get QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u
Big files are split into chunks because:
Chunking strategies (set with --chunker):
| Strategy | Description | Best For |
|---|---|---|
size-N | Fixed size chunks | General use |
rabin | Content-defined chunks using rolling hash | Deduplication across similar files |
buzhash | Alternative content-defined chunking | Similar to rabin |
See ipfs add --help for current defaults, or Import for making them permanent.
Content-defined chunking (rabin/buzhash) finds natural boundaries in the data. This means if you edit the middle of a file, only the changed chunks need to be re-stored - the rest can be deduplicated.
Each chunk becomes a leaf node in a tree. If a file has many chunks, intermediate nodes group them together. This creates a Merkle DAG (Directed Acyclic Graph) where:
Layout strategies:
Balanced layout (default):
graph TD
Root --> Node1[Node]
Root --> Node2[Node]
Node1 --> Leaf1[Leaf]
Node1 --> Leaf2[Leaf]
Node2 --> Leaf3[Leaf]
All leaves at similar depth. Good for random access - you can jump to any part of the file efficiently.
Trickle layout (--trickle):
graph TD
Root --> Leaf1[Leaf]
Root --> Node1[Node]
Root --> Node2[Node]
Node1 --> Leaf2[Leaf]
Node2 --> Leaf3[Leaf]
Leaves added progressively. Good for streaming - you can start reading before the whole file is added.
As the DAG is built, each node is stored in the blockstore:
~/.ipfs/blocks/)--nocopy): Only references to the original file are stored (saves disk space but the original file must remain in place)By default, added content is pinned (ipfs add --pin=true). This tells your IPFS node to keep this data - without pinning, content may eventually be removed to free up space.
Instead of pinning, you can use the Mutable File System (MFS) to organize content using familiar paths like /photos/vacation.jpg instead of raw CIDs:
# Add directly to MFS path
ipfs add --to-files=/backups/ myfile.txt
# Or copy an existing CID into MFS
ipfs files cp /ipfs/QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u /docs/hello.txt
Content in MFS is implicitly pinned and stays organized across node restarts.
Run ipfs add --help to see all available options for controlling chunking, DAG layout, CID format, pinning behavior, and more.
IPFS uses UnixFS to represent files and directories. UnixFS is an abstraction layer that:
/foo/bar.txt instead of just hashes)With --raw-leaves, leaf nodes store raw data without the UnixFS wrapper. This is more efficient and is the default when using CIDv1.
The add flow spans several layers:
flowchart TD
subgraph CLI ["CLI Layer (kubo)"]
A["core/commands/add.go
parses flags, shows progress"]
end
subgraph API ["CoreAPI Layer (kubo)"]
B["core/coreapi/unixfs.go
UnixfsAPI.Add() entry point"]
end
subgraph Adder ["Adder (kubo)"]
C["core/coreunix/add.go
orchestrates chunking, DAG building, MFS, pinning"]
end
subgraph Boxo ["boxo libraries"]
D["chunker/ - splits data into chunks"]
E["ipld/unixfs/ - DAG layout and UnixFS format"]
F["mfs/ - mutable filesystem abstraction"]
G["pinning/ - pin management"]
H["blockstore/ - block storage"]
end
A --> B --> C --> Boxo
| Component | Location |
|---|---|
| CLI command | core/commands/add.go |
| API implementation | core/coreapi/unixfs.go |
| Adder logic | core/coreunix/add.go |
| Chunking | boxo/chunker |
| DAG layouts | boxo/ipld/unixfs/importer |
| MFS | boxo/mfs |
| Pinning | boxo/pinning/pinner |
The Adder type in core/coreunix/add.go is the workhorse. It:
Key methods:
AddAllAndPin() - main entry pointaddFileNode() - handles a single file or directoryadd() - chunks data and builds the DAG using boxo's layout builders