Skip to content

R2Bucket

Source: src/Cloudflare/R2/R2Bucket.ts

A Cloudflare R2 object storage bucket with S3-compatible API.

R2 provides zero-egress-fee object storage. Create a bucket as a resource, then bind it to a Worker to read and write objects at runtime.

Basic R2 bucket

const bucket = yield* Cloudflare.R2Bucket("MyBucket");

Bucket with location hint

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
locationHint: "wnam",
});

Reading and writing objects

const bucket = yield* Cloudflare.R2Bucket.bind(MyBucket);
// Write an object
yield* bucket.put("hello.txt", "Hello, World!");
// Read an object
const object = yield* bucket.get("hello.txt");
if (object) {
const text = yield* object.text();
}

Streaming upload with content length

const bucket = yield* Cloudflare.R2Bucket.bind(MyBucket);
yield* bucket.put("upload.bin", request.stream, {
contentLength: Number(request.headers["content-length"] ?? 0),
});

Attach one or more custom domains to serve bucket objects from a hostname you control. The domain’s zone must already exist in your Cloudflare account; the zone is inferred from the hostname when omitted, or you can pass a Cloudflare.Zone resource, a zone ID, or any hostname inside the zone via the zone field.

Single custom domain

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
domains: [{ name: "assets.example.com" }],
});

Multiple custom domains

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
domains: [
{ name: "assets.example.com" },
{ name: "static.example.com" },
],
});

Disable a custom domain without removing it

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
domains: [{ name: "assets.example.com", enabled: false }],
});

Custom domain with explicit zone and TLS settings

const zone = yield* Cloudflare.Zone("ExampleZone", {
name: "example.com",
});
const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
domains: [
{
name: "assets.example.com",
zone,
minTLS: "1.2",
},
],
});

Configure lifecycle rules to automatically delete objects, abort incomplete multipart uploads, or transition objects to InfrequentAccess storage. Pass an empty array (or omit) to clear all rules. See the Cloudflare R2 docs for details and limits (max 1000 rules per bucket).

Delete objects 30 days after upload

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
lifecycleRules: [
{
id: "expire-old-objects",
deleteObjectsTransition: {
condition: { type: "Age", maxAge: 60 * 60 * 24 * 30 },
},
},
],
});

Transition to InfrequentAccess after 60 days, delete after 365

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
lifecycleRules: [
{
id: "archive-then-delete",
prefix: "logs/",
storageClassTransitions: [
{
condition: { type: "Age", maxAge: 60 * 60 * 24 * 60 },
storageClass: "InfrequentAccess",
},
],
deleteObjectsTransition: {
condition: { type: "Age", maxAge: 60 * 60 * 24 * 365 },
},
},
],
});

Abort incomplete multipart uploads after 7 days

const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
lifecycleRules: [
{
id: "abort-stale-uploads",
abortMultipartUploadsTransition: {
condition: { type: "Age", maxAge: 60 * 60 * 24 * 7 },
},
},
],
});