Securing and Setting Up R2
Public and private files, setting up a bucket, and R2 pricing

Sprout presents
Public files, private files, one bucket and a pricing table. I find bucket permissions genuinely thrilling, so let's set yours up properly.Public files, private files, one bucket and a pricing table. I find bucket permissions genuinely thrilling, so let's set yours up properly.

Security Considerations#
Not every file should be public. Think about what you're storing.
Public Files#
- Profile pictures
- Blog post images
- Product photos
These can have public URLs that anyone can open.
Private Files#
- Personal documents
- Paid content
- Sensitive uploads
These should require someone to be signed in. R2 supports "signed URLs," which are temporary links that expire after a set time. In this snippet, client is the S3 client you'll create in the next lesson, and the GetObjectCommand says which file to share.
import { GetObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
// Generate a temporary URL that expires in 1 hour
const command = new GetObjectCommand({ Bucket: 'my-bucket', Key: 'invoices/1234.pdf' })
const signedUrl = await getSignedUrl(client, command, { expiresIn: 3600 })getSignedUrl lives in its own package, so install it with npm install @aws-sdk/s3-request-presigner next to @aws-sdk/client-s3.
Only signed-in users can request a signed URL, and it only works for a limited time. Somebody forwards the link next week? Dead link.
Setting Up R2#
Here's the basic process to get R2 up and running.
Step 1. Create Cloudflare Account#
Sign up at cloudflare.com. R2 comes with free monthly usage (more on that in Pricing below).
Step 2. Enable R2#
In the Cloudflare dashboard, go to Storage & databases, then R2, and go through the checkout to add an R2 subscription. Yep, even the free usage needs that step, so don't be surprised if it asks for billing info. You don't pay anything until you go past the free amounts.
Step 3. Create a Bucket#
A bucket is where your files live. Give it a name that actually describes what's in it (future you will thank you).
Step 4. Get API Credentials#
On the R2 page, find API Tokens under Account Details and click Manage. Create a token with only the permissions your app needs, and you'll get an Access Key ID and a Secret Access Key. Copy the secret RIGHT AWAY, because Cloudflare only shows it once.
Step 5. Connect Your App#
Use the S3 SDK in your code to upload and grab files.
Pricing#

R2 pricing is simple and pretty cheap. Here's the standard storage pricing as of October 2026 (always double check the R2 pricing page before you promise a client anything).
- Free every month. 10 GB of storage, 1 million Class A operations (writes, like uploads) and 10 million Class B operations (reads)
- Storage after that. $0.015 per GB per month
- Operations after that. $4.50 per million Class A and $0.36 per million Class B
- Egress. FREE! (This is where the big savings are)
For context, a small app storing 10 GB of images fits inside the free tier, so it costs $0. Even at 100 GB you'd pay for the 90 GB over the free amount, which works out to about $1.35 a month. That's thousands and thousands of images for less than a fancy coffee.
This lesson ends with 2 short activities.
