# B2 storage

> A Backblaze B2 bucket with credentials scoped to it, at the lowest price per byte.

```bash
npx extraorbital add b2
```

```txt
✓ Provisioned b2/default (bucket eo-a1b2c3-cosmic-otter-default, us-west-004)
✓ Wrote 5 variables to .env

  B2_BUCKET, B2_ENDPOINT, B2_REGION, B2_ACCESS_KEY_ID, B2_SECRET_ACCESS_KEY
```

A project that mentions any `B2_*` variable gets this from
[`extraorbital provision`](/docs/quickstart#how-autopilot-decides) without naming it.

B2 is S3-compatible, so every S3 client works against it unchanged. It is the
cheapest of the three per byte stored — about a third of [`r2`](/docs/resources/r2)
and a quarter of [`s3`](/docs/resources/s3) — and it charges nothing for
operations. The trade is bandwidth: egress is free only up to three times what
you store.

## What it writes

| Variable | Example |
| --- | --- |
| `B2_BUCKET` | `eo-a1b2c3-cosmic-otter-default` |
| `B2_ENDPOINT` | `https://s3.us-west-004.backblazeb2.com` |
| `B2_REGION` | `us-west-004` |
| `B2_ACCESS_KEY_ID` | `0045f1a…` |
| `B2_SECRET_ACCESS_KEY` | `K004…` |

The key reaches that bucket and no other. Bucket names carry a prefix because
Backblaze names are unique across all of Backblaze, not just within an account.

## Options

```bash
npx extraorbital add b2 [--slug <name>] [--public]
```

| Flag | Default | Description |
| --- | --- | --- |
| `--slug` | `default` | A second, fully separate bucket in the same project |
| `--public` | off | Objects are publicly readable |

There is no `--region`: Backblaze puts a bucket where the account lives, and
`B2_REGION` reports where that turned out to be.

Options apply at creation. Re-running `add` with different options returns the
existing bucket unchanged — remove it first if you need a different one.

## What it costs

Backblaze's published rates, passed on unchanged, counted against your plan's
allowance:

| | Rate |
| --- | --- |
| Storage | $0.00695 / GB-month ($6.95 / TB) |
| Operations | **free** — uploads, downloads, listing and copies alike |
| Egress | free up to 3× what you store, then $0.01 / GB |

Two honest caveats.

**Egress is not billed per bucket.** Backblaze reports no per-bucket download
counter, so an overage cannot be attributed to the bucket that caused it. We
watch the account-level ceiling instead rather than invent a share — but if you
serve far more than you store, [`r2`](/docs/resources/r2) has no egress charge at
all and is the better fit.

**Storage is sampled, not replayed.** Backblaze publishes no usage history, so a
day is billed on a reading taken during it rather than reconstructed afterwards.

Usage appears in `extraorbital ledger` a day at a time, once each UTC day has
closed.

## File retention on the Free plan

On the Free plan, **files are hidden 30 days after they are uploaded and deleted
10 days after that**. Backblaze does this itself, as a bucket lifecycle rule;
nothing of ours sweeps your bucket.

Those ten days are the point. A hidden file is invisible to reads and lists but
still there, so a free account that starts paying within the window gets its files
back. After the window they are gone, and [`r2`](/docs/resources/r2) has no window
at all — its expiry is an outright delete.

Paying lifts the rule within the hour. Lifting it stops further expiry; it does not
un-delete anything already past the ten days.

You cannot change this yourself: the key you are given can read and write objects,
not reconfigure the bucket, which is what makes the rule a rule.

This is separate from the 30-day idle rule that deletes an unused *resource*: a
busy free bucket survives that one and still loses last month's files.

## Use it

```ts title="storage.ts"
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const b2 = new S3Client({
  region: process.env.B2_REGION,
  endpoint: process.env.B2_ENDPOINT,
  forcePathStyle: true,
  credentials: {
    accessKeyId: process.env.B2_ACCESS_KEY_ID!,
    secretAccessKey: process.env.B2_SECRET_ACCESS_KEY!,
  },
});

await b2.send(
  new PutObjectCommand({ Bucket: process.env.B2_BUCKET, Key: "report.json", Body: data }),
);
```

## Next

- [R2 storage](/docs/resources/r2) — free egress, if you read more than you store
- [Quickstart](/docs/quickstart) — slugs, idempotency and sharing
- [Pricing](/pricing) — plans, allowances and rates

---

More for agents: [Docs index](https://extraorbital.dev/sitemap.md) · [llms.txt](https://extraorbital.dev/llms.txt) · [agents.md](https://extraorbital.dev/agents.md)
