Source constraint: All information in this skill is sourced from the Walrus managing blobs documentation and the large uploads guide. When extending this skill, only pull from these sources.
Walrus blobs have finite lifetimes measured in epochs. This skill covers all post-storage operations: extending lifetimes, deleting, burning, sharing, setting attributes, and planning large data uploads.
All patterns in this skill are derived from:
- https://docs.wal.app/docs/walrus-client/managing-blobs
- https://docs.wal.app/docs/walrus-client/storing-blobs (lifetime options)
- https://docs.wal.app/docs/large-uploads
If unsure about any lifecycle operation, fetch the relevant page before answering.
Reference files
large-uploads — Large Data Upload Patterns
Path: large-uploads.md
Load when: planning uploads larger than 1 GiB, estimating storage costs for large datasets, managing concurrent upload memory, or building ingestion pipelines.
Covers: cost estimation, tuning for >1 GiB uploads, upload observability, pipeline state persistence, throughput management, memory overhead (4.5x blob size).
Related skills
| Topic | Skill | Load when |
|---|---|---|
| Basic store/read | walrus-cli |
Storing and reading blobs |
| HTTP API | walrus-http-api |
Store/read via REST |
| TypeScript SDK | walrus-ts-sdk |
Programmatic blob management |
| Quilts | walrus-quilts |
Lifecycle operations on quilts (apply to whole quilt) |
| Encryption | walrus-data-security |
Encrypting before storage |
| Move integration | walrus-move-integration |
On-chain blob references |
Routing guide
| Task | Load |
|---|---|
| Extend a blob's lifetime | Skill Content |
| Delete a deletable blob | Skill Content |
| Burn a blob's Sui object | Skill Content |
| Create or fund a shared blob | Skill Content |
| Set/get/remove blob attributes | Skill Content |
| Plan a large data upload (>1 GiB) | large-uploads.md |
| Estimate storage costs | large-uploads.md |
| Build an ingestion pipeline | large-uploads.md |
| Manage concurrent upload memory | large-uploads.md |
Skill Content
Key concepts
-
Epochs and lifetimes. Blob storage duration is measured in epochs. A Mainnet epoch is 14 days. Maximum storage is 53 epochs (approximately 2 years). A blob expires at the beginning of its end epoch. Use
walrus infoorGET /v1/infoon an aggregator to check the current epoch and duration. -
Blob ID vs Sui object ID. A blob ID is a URL-safe base64 string derived from the blob content (content-addressed). The same content always produces the same blob ID. A Sui object ID is a
0x...hex string identifying the on-chainBlobobject. Each upload creates a new object ID even for identical content. Use blob ID for reading content, object ID for lifecycle operations (extend, delete, share). -
Deletable vs permanent. Newly stored blobs are deletable by default. Deletable blobs can be removed by the Sui object owner before expiry. Permanent blobs cannot be deleted before expiry, even by the uploader.
-
What happens when a blob expires. When a blob's end epoch is reached, the data becomes unavailable. There is no grace period. Storage nodes discard slivers. You must re-upload the data to make it available again. Expired blobs cannot be extended.
-
Wrapping blobs in shared objects. A
Blobobject can be wrapped into any Sui shared object, allowing multiple parties to fund and extend it. The Walrus contract providesshared_blob::SharedBlobas one reference implementation of this pattern, but developers are free to create their own shared wrapper with custom logic (access control, metadata, etc.). -
Storage pools. A preview feature: one storage reservation that many blobs share. Pooled blobs draw on the pool's pre-paid capacity, so each store pays only the write fee, and all blobs in a pool expire together. Available through the Rust SDK (
walrus-sdk,walrus-sui) and the Move contracts; thewalrusCLI, the HTTP publisher and aggregator APIs, and the TypeScript SDK do not expose pools yet. -
Blob attributes. Key-value metadata pairs stored on the blob's Sui object. Certain keys (
content-type,content-disposition, and others) are recognized by the aggregator and returned as HTTP headers when reading by object ID. -
Per-blob storage overhead. Each blob incurs approximately 64 MB of metadata overhead regardless of size. For blobs smaller than ~10 MB, this metadata cost dominates. Use quilts for batching many small blobs to amortize this overhead.
Check status and verify availability before acting
Before you extend or depend on a blob, confirm it is still stored and see when it expires:
walrus blob-status --blob-id <BLOB_ID> # stored? availability period; event ID for certified permanent blobs
walrus info # current epoch, to compare against the end epoch
Expiry is silent: at the end epoch, storage nodes stop serving the blob and no event is emitted. Check on a schedule rather than waiting for a read to fail, and extend well before the end epoch.
To check programmatically after a write, re-read the Blob object from Sui using the object ID from the write result. A blob is durable when it is certified, the current epoch is before its end epoch, and it is not deletable:
const blob = await walrusClient.getBlobObject(blobObjectId);
const durable = blob.certified_epoch != null && currentEpoch < blob.storage.end_epoch && !blob.deletable;
For integrity, read the bytes by object ID through an aggregator with strict_consistency_check=true, so the data is bound to the object whose certification you verified. The blob_id field on the Sui object is a u256, not the base64 ID used in URLs.
Extend blob lifetime
# Extend by blob Sui object ID
walrus extend --blob-obj-id <BLOB_OBJECT_ID>
# Extend with a specific new end epoch
walrus extend --blob-obj-id <BLOB_OBJECT_ID> --end-epoch <EPOCH>
# Extend a shared blob (requires --shared flag)
walrus extend --blob-obj-id <BLOB_OBJECT_ID> --shared
- The blob must not be expired.
- Both owned and shared blobs can be extended.
- Only the owner can extend owned blobs. Anyone can extend shared blobs.
- You need the blob's Sui object ID (not the blob ID).
Delete blobs
# Delete by blob ID
walrus delete --blob-id <BLOB_ID>
# Delete by file (derives blob ID)
walrus delete --file <PATH>
# Delete by Sui object ID
walrus delete --object-id <SUI_ID>
# Skip confirmation prompt
walrus delete --blob-id <BLOB_ID> --yes
# Skip post-delete status check
walrus delete --blob-id <BLOB_ID> --yes --no-status-check
Important caveats:
- Only the owner of the Sui
Blobobject can delete a deletable blob. - Delete reclaims the storage resource, which is reused automatically.
- Delete only removes slivers from current and future storage nodes. If another copy of the same blob exists (uploaded by someone else), the data remains accessible.
- Delete has limited utility for privacy. All blobs are public. Cached or previously downloaded copies are not affected.
Burn blobs
Burning removes the blob's Sui object without deleting data from Walrus and without refunding storage:
# Burn a specific blob by object ID
walrus burn-blobs --object-ids <BLOB_OBJECT_ID>
# Burn all blob objects owned by the current wallet
walrus burn-blobs --all
# Burn all expired blob objects
walrus burn-blobs --all-expired
After burning, you cannot extend permanent blobs or extend/delete deletable blobs. You lose all control of the blob.
Shared blobs
A blob can be wrapped into a Sui shared object so that anyone can fund and extend it. The Walrus contract provides shared_blob::SharedBlob as one reference implementation, but you can also wrap a Blob into your own custom shared object with whatever logic you need.
Using the built-in SharedBlob via the CLI:
# Share an existing blob using the built-in SharedBlob
walrus share --blob-obj-id <SUI_OBJ_ID>
# Fund an existing shared blob
walrus fund-shared-blob --blob-obj-id <SHARED_OBJ_ID> --amount <WAL_AMOUNT>
# Store and share in one step
walrus store myfile.png --epochs 10 --share
Built-in shared blobs:
- Can only contain permanent blobs
- Cannot be deleted before expiry
- Anyone can fund and extend them
For more control, consider wrapping the Blob in your own shared object (see walrus-move-integration).
Storage pools (preview)
A storage pool is a single storage reservation that many blobs share. In the standard flow every blob buys its own storage resource for its exact size and lifetime; with a pool you reserve a block of encoded capacity for a lifetime once, and each blob registered into it pays only the write fee.
| Regular blob | Pooled blob | |
|---|---|---|
| Storage payment | Own storage resource per blob | Draws on the pool's pre-paid capacity; registration pays only the write fee |
| Lifetime | Individual expiry, extended per blob | Shares the pool's expiry; extending the pool extends every blob in it |
| Deletion | Returns the storage resource to you | Frees its encoded size for the next blob in the pool (no WAL refund) |
| Ownership | Blob can be owned, transferred, shared |
PooledBlob lives inside the pool and cannot be transferred on its own |
| Reading | By blob ID | Identical; pooled blobs have regular blob IDs |
Costs: creating a pool pays the storage fee for the full reserved capacity for its full lifetime, whether or not blobs fill it; registering a blob pays the write fee for its encoded size; extending or growing the pool pays the storage fee for the added epochs or capacity; deleting pays nothing and refunds nothing. The fixed per-blob metadata overhead still applies to pooled blobs, so pools do not make many small blobs cheaper; use quilts for that, optionally inside a pool.
Use a pool when you continuously write and retire blobs against a predictable total footprint, want each write to cost only the write fee, and can accept one shared expiry. Prefer regular blobs when blobs need independent lifetimes, when you need to transfer or share individual blob objects, or when capacity needs are unpredictable.
Pools are available through the Rust SDK (create_storage_pool, reserve_and_store_blobs_in_storage_pool, storage_pool_status, delete_pooled_blob, extend_storage_pool, increase_storage_pool_capacity) and the walrus::system Move module. The walrus CLI has no pool support; there is no --storage-pool flag. See the storage pools page for the Rust and Move examples.
Blob attributes
# Set attributes (multiple key-value pairs supported)
walrus set-blob-attribute <BLOB_OBJECT_ID> --attr "content-type" "image/png" --attr "creator" "myapp"
# Get attributes
walrus get-blob-attribute <BLOB_OBJECT_ID>
# Remove all attributes
walrus remove-blob-attribute <BLOB_OBJECT_ID>
# Remove specific keys
walrus remove-blob-attribute-fields <BLOB_OBJECT_ID> --keys "creator"
Recognized HTTP header attribute keys: content-disposition, content-encoding, content-language, content-location, content-type, link. These are returned as HTTP headers when reading by object ID.
Rules
- Blobs expire at the beginning of the end epoch. A blob with end epoch 314 becomes unavailable at the start of epoch 314. Plan accordingly.
- You cannot extend expired blobs. Extend before expiration. Monitor expiration with
walrus blob-status. - Delete does not guarantee data removal. Other copies of the same blob might exist. Caches and past storage nodes are not affected.
- Shared blobs must be permanent. You cannot share a deletable blob. Convert to permanent first or store as permanent with
--share. - Burn is irreversible. Burning a blob object forfeits all control with no storage refund. Use
--all-expiredto clean up expired blobs safely. - Maximum blob size is approximately 13.6 GiB. Check the current limit with
walrus infounder "Maximum blob size." For large uploads, see thelarge-uploads.mdreference file.
Common mistakes
- Inventing a
--storage-poolCLI flag. Pools are not in the CLI; they are a Rust SDK and Move preview. - Waiting for a read to fail to learn a blob expired. Expiry emits no event. Check
blob-statusagainstwalrus infoon a schedule. - Extending with the blob ID instead of the object ID. The
extendcommand requires--blob-obj-id(Sui object ID), not the blob ID. - Trying to extend an expired blob. Once expired, a blob cannot be extended. You must re-upload.
- Expecting delete to make data completely unavailable. If another user uploaded the same content, it persists. Encryption is the only reliable privacy mechanism.
- Burning blobs that still have value. Burning is permanent, forfeits storage, and provides no refund. Use
deleteto reclaim storage instead. - Sharing a deletable blob. Shared blobs require permanent blobs. Store with
--permanent --shareor ensure the blob is permanent before sharing. - Storing with
--epochs 1near an epoch boundary. The blob expires almost immediately. Use generous epoch counts.