SiaSia Developer Portal

Upload Packing

Sia erasure-codes every upload into a fixed number of shards (by default, 10 data + 20 parity = 30 shards). Each shard is a fixed-size sector stored on a different storage provider. This means even a 1-byte file occupies a full slab — the same storage footprint as a file that fills the entire slab's data capacity.

For apps that store many small files (chat messages, thumbnails, config blobs, etc.), uploading each one individually wastes most of every slab. Packed uploads solve this by combining multiple small objects into a shared slab before erasure coding, so they split the overhead instead of each paying the full cost.

Each packed object still gets its own Object ID and can be pinned, downloaded, shared, or deleted independently.

rust
use std::io::Cursor; use std::time::Instant; let start = Instant::now(); let mut packed = sdk.upload_packed(UploadOptions::default()); for i in 0..10 { let data = format!("Contents of object {}.", i + 1); let reader = Cursor::new(data.into_bytes()); let size = packed.add(reader).await?; let rem = packed.remaining(); println!("Object {} added: {} bytes ({} remaining)", i + 1, size, rem); } let mut objects = packed.finalize().await?; for (i, obj) in objects.iter_mut().enumerate() { obj.metadata = format!(r#"{{"File Name":"packed-{}.txt"}}"#, i + 1).into_bytes(); sdk.pin_object(obj).await?; } let elapsed = start.elapsed(); println!("\nPacked upload finished {} objects in {:.2?}", objects.len(), elapsed); for (i, obj) in objects.iter().enumerate() { println!(" - Object {} ID: {}", i + 1, obj.id()); }