# Storage Operations

:::tip[Purpose]
This guide shows you how to get started with storage operations in Synapse SDK.
You'll learn the fundamentals of uploading data, managing data sets, and retrieving stored content.

**Audience**: Developers new to Synapse SDK storage capabilities
**Time to complete**: 10-15 minutes
**Prerequisites**: Basic TypeScript knowledge, Synapse SDK installed
:::

This guide explains the core storage concepts and provides examples of how to use the Synapse SDK to store, retrieve, and manage data on Filecoin On-Chain Cloud.

## Key Concepts

**Data Set**: A logical container of pieces stored with one provider. When a data set is created, a payment rail is established with that provider. All pieces in the data set share this single payment rail and are verified together via PDP proofs.

**PieceCID**: Content-addressed identifier for your data (format: `bafkzcib...`). Automatically calculated during upload and used to retrieve data from any provider.

**Metadata**: Optional key-value pairs for organization:

- **Data Set Metadata**: Max 10 keys (e.g., `project`, `environment`)
- **Piece Metadata**: Max 5 keys per piece (e.g., `filename`, `contentType`)

**Storage Manager**: The main entry point for storage operations. Handles provider selection, data set management, and provides downloads from any provider (provider-agnostic) using the StorageContext.

**Storage Context**: A connection to a specific storage provider and data set. Created explicitly for fine-grained control or automatically by StorageManager. Enables uploads and downloads with the specific storage provider.

## Storage Approaches

The SDK offers two ways to work with storage operations:

| Approach             | Who It's For    | What SDK Handles                                  | When to Use                                             |
| -------------------- | --------------- | ------------------------------------------------- | ------------------------------------------------------- |
| **Auto-Managed**     | Most developers | Provider selection, data set creation, management | Getting started, simple apps, quick prototypes          |
| **Explicit Control** | Advanced users  | Nothing - you control everything                  | Batch operations, specific providers, cost optimization |

**Recommendation**: Start with auto-managed, then explore explicit control only if needed.

### Example 1: Quick Start (Auto-Managed)

Upload and download data with zero configuration - SDK automatically selects a provider and manages the data set:

```ts twoslash
// @lib: esnext,dom
import { Synapse } from "@filoz/synapse-sdk";
import { privateKeyToAccount } from 'viem/accounts'

const synapse = Synapse.create({ account: privateKeyToAccount('0x...') });
// ---cut---
const data = new Uint8Array([1, 2, 3, 4, 5]);

const { pieceCid } = await synapse.storage.upload(data);
const downloaded = await synapse.storage.download({ pieceCid });

console.log("Uploaded:", pieceCid);
console.log("Downloaded:", downloaded.length, "bytes");
```

### Example 2: With Metadata (Auto-Managed)

Add metadata to organize uploads and enable faster data set reuse - SDK will reuse any existing data set matching the metadata:

```ts twoslash
// @lib: esnext,dom
import { Synapse } from "@filoz/synapse-sdk";
import { privateKeyToAccount } from 'viem/accounts'

const data = new Uint8Array([1, 2, 3, 4, 5]);
const synapse = Synapse.create({ account: privateKeyToAccount('0x...') });
// ---cut---
const context = await synapse.storage.createContext({
  metadata: {
    Application: "My DApp",
    Version: "1.0.0",
    Category: "Documents",
  },
});

const result = await synapse.storage.upload(data, { context });
console.log("Uploaded:", result.pieceCid);
```

:::tip[Need More Control?]
The examples above use auto-managed storage where the SDK handles provider selection and data set creation.

**For advanced use cases** like batch uploads, custom callbacks, or explicit provider selection, see the [Storage Context Guide](/developer-guides/storage/storage-context/).
:::

## Data Set Management

:::note[When You Need This]
These APIs are useful when you want to inspect existing data sets, query stored pieces, or retrieve metadata. For basic upload/download, you don't need these.
:::

Data sets are automatically created during your first upload to a provider. For explicit management of data sets, use these operations:

**When You Need Explicit Data Sets:**

- Uploading many files to same provider
- Want consistent provider for your application
- Need to track costs per data set
- Building batch upload workflows

### Getting all data sets

Retrieve all data sets owned by your account to inspect piece counts, CDN status, and metadata:

```ts twoslash
// @lib: esnext,dom
import { Synapse } from "@filoz/synapse-sdk";
import { privateKeyToAccount } from 'viem/accounts'

const synapse = Synapse.create({ account: privateKeyToAccount('0x...') });
// ---cut---
const dataSets = await synapse.storage.findDataSets();

for (const ds of dataSets) {
  console.log(`Dataset ${ds.pdpVerifierDataSetId}:`, {
    live: ds.isLive,
    cdn: ds.withCDN,
    pieces: ds.activePieceCount,
    metadata: ds.metadata
  });
}
```

### Getting data set pieces

List all pieces stored in a specific data set by iterating through the context:

```ts twoslash
// @lib: esnext,dom
import { Synapse } from "@filoz/synapse-sdk";
import { privateKeyToAccount } from 'viem/accounts'

const synapse = Synapse.create({ account: privateKeyToAccount('0x...') });
const dataSetId = 1n;
// ---cut---
const context = await synapse.storage.createContext({ dataSetId });

const pieces = [];
for await (const piece of context.getPieces()) {
  pieces.push(piece);
}
console.log(`Found ${pieces.length} pieces`);
```

### Getting a data set piece metadata

Access custom metadata attached to individual pieces for organization and filtering:

```ts twoslash
// @lib: esnext,dom
import { WarmStorageService } from "@filoz/synapse-sdk/warm-storage";
import { privateKeyToAccount } from 'viem/accounts'
const dataSetId = 1n;
const piece = null as unknown as { pieceCid: string; pieceId: bigint };
// ---cut---
const warmStorage =  WarmStorageService.create({ account: privateKeyToAccount('0x...') });

const metadata = await warmStorage.getPieceMetadata({ dataSetId, pieceId: piece.pieceId });
console.log("Piece metadata:", metadata);
```

## Getting the size of a specific piece

Calculate size of a specific piece by extracting the size from the PieceCID:

```ts twoslash
// @lib: esnext,dom
const pieceCid = null as unknown as string;
// @ts-ignore
// ---cut---
import { getSizeFromPieceCID } from "@filoz/synapse-sdk/piece";

const size = getSizeFromPieceCID(pieceCid);
console.log(`Piece size: ${size} bytes`);
```

## Storage Information

Query service-wide pricing, available providers, and network parameters:

```ts twoslash
// @lib: esnext,dom
import { Synapse } from "@filoz/synapse-sdk";
import { privateKeyToAccount } from 'viem/accounts'

const synapse = Synapse.create({ account: privateKeyToAccount('0x...') });
// ---cut---
const info = await synapse.storage.getStorageInfo();
console.log("Price/TiB/month:", info.pricing.noCDN.perTiBPerMonth);
console.log("Providers:", info.providers.length);

const providerInfo = await synapse.getProviderInfo("0x...");
console.log("PDP URL:", providerInfo.pdp.serviceURL);
```

## Next Steps

**Ready to explore more?** Here's your learning path:

- **[Advanced Operations →](/developer-guides/storage/storage-context/)**
  Learn about batch uploads, lifecycle management, and download strategies.
  _For developers building production applications with specific provider requirements._

- **[Plan Storage Costs →](/developer-guides/storage/storage-costs/)**
  Calculate your monthly costs and understand funding requirements.
  _Use the quick calculator to estimate costs in under 5 minutes._

- **[Payment Management →](/developer-guides/payments/payment-operations/)**
  Manage deposits, approvals, and payment rails.
  _Required before your first upload._