# Storage

Fleet stores all artifacts (base models, fine-tuned models, checkpoints, and datasets) in cloud object storage. Storage is metered and billed daily based on how much you have stored.

## What gets stored

| Artifact | When | Typical size |
|----------|------|-------------|
| Base model | When you push or load from HuggingFace | 1–70 GB |
| Dataset | When you upload a `.jsonl` file | KBs–GBs |
| Checkpoint | Every `SAVE_STEPS` steps during training | Same as base model |
| Fine-tuned model | When training completes | Same as base model (full) or adapter only (LoRA) |

## Storage pricing

Storage is charged at **$0.01875/GB/month**, billed daily. Charges appear in your ledger as `storage` transactions.

## Viewing usage

```python
info = client.billing()
print(info["storage_gb"])              # e.g. 12.4
print(info["storage_cost_per_month"])  # e.g. 0.2325
```

```bash
# Shown automatically in fleet billing output
fleet billing   # (if available in your dashboard)
```

## Controlling checkpoint storage

Checkpoints are the biggest source of storage growth. A LoRA checkpoint is typically 100–300 MB; saving every 100 steps over 10,000 steps produces 100 checkpoints = ~15–30 GB.

Fleet enforces a **rolling checkpoint limit** per job. When a new checkpoint is saved and the limit is exceeded, the oldest checkpoint is deleted automatically from both storage and your model list.

Default limit: **1 checkpoint per job**, sufficient for crash recovery without accumulating storage.

Adjust it:

```bash
fleet settings set max_checkpoints 5   # keep only the 5 most recent
fleet settings set max_checkpoints 50  # keep up to 50
```

```python
client.update_settings(max_checkpoints=5)
```

### Pruning on completion

By default, all checkpoints are deleted when a job completes successfully. The final output model is stored separately and is unaffected. This keeps storage costs near zero for completed jobs.

To retain checkpoints after completion (e.g. for analysis or rollback):

```bash
fleet settings set prune_checkpoints_on_completion false
```

```python
client.update_settings(prune_checkpoints_on_completion=False)
```

## Downloading artifacts

### Models

Get presigned download URLs for all files in a model:

```python
files = model.download()
for f in files:
    print(f["filename"], f["url"])
```

```bash
fleet models download <model_id>
```

URLs are valid for **1 hour**. Download files directly from the URLs. No Fleet credentials required.

A typical download flow:

```python
import httpx
from pathlib import Path

model = client.models.get("model_abc123")
files = model.download()

out = Path("./downloaded-model")
out.mkdir(exist_ok=True)

for f in files:
    dest = out / f["filename"]
    dest.parent.mkdir(parents=True, exist_ok=True)
    with httpx.stream("GET", f["url"]) as r:
        with open(dest, "wb") as fh:
            for chunk in r.iter_bytes():
                fh.write(chunk)
```

### Datasets

```python
result = dataset.download()
print(result["url"])   # presigned URL, 1 hour TTL
```

```bash
fleet datasets download <dataset_id>
```

## Deleting artifacts

Storage is decremented immediately when you delete an artifact.

```python
# Delete a model (and free its storage)
client._http.delete(f"/v1/models/{model_id}")

# Delete a dataset
client.datasets.delete(dataset_id)
```

```bash
fleet models delete <model_id>
fleet datasets delete <dataset_id>
fleet checkpoints delete <model_id>
```

Deleting a fine-tuned model or checkpoint does not affect the base model it was trained from.
