If you’re running apps on a VPS and you’re debating cloudflare r2 vs s3, the decision isn’t really about “which object storage is better.” It’s about where your costs come from, how your traffic leaves the provider, and how much AWS compatibility you actually need.
In VPS_HOSTING setups (think Docker apps on digitalocean or bare-metal-ish VMs from hetzner), object storage is usually the cheapest part—until egress and cross-region access start quietly dominating your bill.
1) The big architectural difference: egress economics
Amazon S3 is the default for a reason: it’s everywhere, mature, and integrates with basically every tool. But S3’s cost profile can be punishing for bandwidth-heavy workloads. The usual pattern in VPS hosting is:
- Your app runs on a VPS (DigitalOcean, Hetzner, Linode, Vultr, etc.).
- It reads/writes objects (images, backups, user uploads).
- Users download those objects, often through your app or CDN.
With S3, data leaving AWS is often the expensive part. With Cloudflare R2, the headline feature is no egress fees (to the public internet), which can flip the economics if you serve lots of downloads.
Opinionated take: if your project is “serve lots of files to lots of users” (media, archives, game patches, public datasets), egress dominates—R2 can be the most impactful cost lever you can pull. If your project is “store some assets and backups,” S3’s predictability and ecosystem still wins.
2) Compatibility and ecosystem: S3 is the standard; R2 is S3-ish
S3 compatibility is not just a marketing checkbox. It’s the difference between:
- Plugging into existing tooling (backup clients, data pipelines, Terraform modules)
- And spending time debugging edge cases in auth headers, multipart uploads, or SDK behavior
Cloudflare R2 intentionally exposes an S3-compatible API, which means many libraries will work with minimal changes. Still, S3 is the reference implementation, and any “S3-compatible” service can hit sharp edges under unusual workloads.
Where S3 tends to be objectively better:
- Advanced features and deep integrations across AWS
- Mature IAM and enterprise governance patterns
- Multi-region architectures and replication options at scale
Where R2 tends to shine:
- Simpler pricing story (especially around egress)
- Tight integration with cloudflare edge services (CDN, Workers)
If you’re running workloads on a VPS provider like hetzner and want something that “just works” with common S3 tooling, both can work. But S3 has fewer surprises across the long tail.
3) Latency and delivery: CDN-first vs region-first
In VPS hosting, your app server location matters. If your VPS is in Europe and your object storage is in a US region, every request pays a latency tax.
S3 gives you explicit regional placement and a well-understood model: pick the region near your compute (or your users) and optionally put a CDN in front.
R2 is more “edge-native” in how people tend to use it: store objects, then serve them through Cloudflare’s network. In practice this can reduce perceived latency for global users, especially for static assets.
A practical rule:
- If your VPS is the origin and most traffic is dynamic, keep storage near compute.
- If most traffic is static downloads, optimize for delivery at the edge.
This is why R2 often pairs nicely with small VPS instances (DigitalOcean, Vultr, Linode) that shouldn’t be burdened with file serving.
4) Actionable example: switching an S3 client to R2
If your app already uses an S3-compatible SDK, you can often point it at R2 by changing the endpoint and credentials.
Here’s a minimal Node.js example using AWS SDK v3:
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
const client = new S3Client({
region: "auto",
endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
},
});
await client.send(
new PutObjectCommand({
Bucket: "my-bucket",
Key: "uploads/hello.txt",
Body: "hello from a VPS",
ContentType: "text/plain",
})
);
Notes from the trenches:
- Many apps work immediately with an S3-compatible endpoint.
- Test multipart uploads and large objects early.
- If you rely on AWS-specific IAM policies, you’ll need to translate assumptions.
5) Which one should you pick for VPS hosting?
Choose S3 when:
- You need maximum compatibility and the broadest tooling support
- You’re already on AWS or expect to use more AWS services later
- You need mature governance, auditing, or advanced replication patterns
Choose Cloudflare R2 when:
- Your VPS-hosted app serves a lot of public downloads and egress is your pain point
- You want to lean on Cloudflare’s edge to offload bandwidth from your VPS
- You prefer a simpler cost model for “store + deliver” workloads
Soft recommendation (no hard sell): if you host your app on digitalocean or hetzner and your monthly bill is creeping up due to bandwidth, prototype R2 for your static assets first. Keep S3 for workflows that depend on AWS-native features. The best setup in 2026 is often hybrid: pick the storage that matches the traffic shape, not the one with the loudest brand gravity.
Some links in this article are affiliate links. We may earn a commission at no extra cost to you if you make a purchase through them.
Top comments (0)