Skip to content
extraorbital
Documentation ExtraOrbital
Browse documentation

Data & storage

R2 storage

Add a Cloudflare R2 file bucket with free download bandwidth.

Run in your project folder
npx extraorbital add r2

Free-plan files expire after 30 days. Deleted files cannot be restored.

  1. 01 / Run the commandGet the service
  2. 02 / Read your .envUse its credentials
  3. 03 / Connect your appCall the SDK or API

Limits

LimitFree · PrototypePaid
StorageYour allowanceUsage billed
RequestsYour allowanceUsage billed
BandwidthFree egressFree egress
File retentionDeleted 30 days after uploadKept until you delete it
BackupsNoneCharged as storage
Inactive resource30 days after last usePersistent

Free allowances are shared across the account. Provider limits still apply on paid plans.

Use it

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

const r2 = new S3Client({
  region: "auto",
  endpoint: process.env.R2_ENDPOINT,
  // R2 addresses a bucket as a path under the account host, not as a
  // subdomain of it. Without this an SDK on its defaults finds nothing.
  forcePathStyle: true,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID!,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
  },
});

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

Environment variables

The CLI writes these to .env or an existing .env.local.

VariablePurpose
R2_BUCKETBucket name
R2_ENDPOINTEndpoint for the bucket’s jurisdiction
R2_ACCOUNT_IDCloudflare account ID
R2_ACCESS_KEY_IDBucket access key
R2_SECRET_ACCESS_KEYPrivate signing secret

Specifics

Options

Terminal
npx extraorbital add r2 [--slug <name>] [--public] [--region <jurisdiction>]
FlagDefaultDescription
--slugdefaultA second, fully separate bucket in the same project
--publicoffObjects are publicly readable
--regiondefaultAn R2 jurisdiction: default, eu or fedramp

--region selects a storage jurisdiction. eu restricts storage to the European Union. Accepted values are default, eu, and fedramp; other values return an error.

R2_ENDPOINT matches the selected jurisdiction.

Options apply at creation. Reusing a slug does not change the bucket. Use a new slug for a different configuration.

Access

Credentials are limited to this bucket. --public makes objects readable without authentication. Use a new slug for a different configuration; repeating add reuses the existing bucket.

File retention

Free-plan files expire 30 days after upload, under a Cloudflare lifecycle rule.

Upgrading removes the rule within an hour. Deleted files cannot be restored. B2 offers a 10-day recovery window.

Expiry details:

  • Expiry is approximate. Cloudflare typically deletes objects within 24 hours of the deadline.
  • You cannot change this yourself. The supplied credentials manage objects, not bucket lifecycle rules.

File expiry applies even when a bucket is active. The separate inactivity policy deletes resources unused for 30 days.

Pricing

UsagePaid rate
Storage$0.015 / GB-mo
Requests$4.50 / M writes, $0.36 / M reads
BandwidthFree egress

See pricing for team subscription fees, allowances, and billing terms. Plans and billing ↗

Deletes and aborted multipart uploads are free. Usage appears after each UTC day closes.