Compare 7 object storage providers side-by-side. Storage pricing, egress fees, S3 compatibility, free tiers, and code examples. Find the cheapest S3 alternative for your workload.
Object storage lets you store and retrieve files (objects) over HTTP. Every major provider implements the S3 API, making it easy to switch between them.
PUT /bucket/keyGET /bucket/keyObject storage replaces local filesystems and FTP with infinitely scalable, highly durable HTTP-accessible storage.
Raw storage pricing across providers. Backblaze B2 is 4x cheaper than S3 Standard per gigabyte.
Side-by-side feature matrix across all 7 object storage providers.
| Feature | Amazon S3 | Cloudflare R2 | Backblaze B2 | Wasabi | GCS | DO Spaces | MinIO |
|---|---|---|---|---|---|---|---|
| Storage/GB/mo | $0.023 | $0.015 | $0.006 | $0.007 | $0.020 | $0.020 | Self-hosted |
| Egress/GB | $0.09 | $0.00 | $0.01* | $0.00** | $0.12 | $0.01 | Self-hosted |
| PUT/1K requests | $0.005 | $0.0045 | ~$0.004 | $0.00 | $0.005 | Included | Self-hosted |
| GET/1K requests | $0.0004 | $0.00036 | ~$0.0004 | $0.00 | $0.0004 | Included | Self-hosted |
| Free Tier | 5 GB (12 mo) | 10 GB forever | 10 GB forever | 1 TB / 30 days | 5 GB forever | None ($5/mo) | OSS free |
| S3 Compatible | Native | Full | Full | Full | Interop API | Full | Full |
| Storage Classes | 6 (Standard, IA, Glacier...) | 2 (Standard, IA) | 2 (Standard, HiPerf) | 1 | 4 (Standard, Nearline...) | 2 (Standard, Cold) | Configurable |
| Object Versioning | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Object Lock (WORM) | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ |
| Lifecycle Rules | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Encryption at Rest | SSE-S3/KMS/C | AES-256 | SSE-B2/C | AES-256 | GKMS/CMEK | AES-256 | SSE-S3/KMS/C |
| CDN Integration | CloudFront | Built-in (CF network) | Partner (CF, Fastly) | None | Cloud CDN | Built-in CDN | Self-configured |
| Regions | 30+ | Auto (global hints) | 2 (US, EU) | 16+ | 35+ | 7 | Self-hosted |
| Max Object Size | 5 TB | 5 TB (multipart) | 10 GB (S3), 5 TB (native) | 5 TB | 5 TB | 5 GB | 50 TB |
* B2 egress free up to 3x stored data and free to CDN partners (Cloudflare, Fastly) ** Wasabi egress free within fair-use policy (download ≤ stored volume)
Detailed breakdown of each provider with pros, cons, and best use cases.
Data transfer (egress) fees can exceed storage costs. If you serve files to users, egress pricing is critical.
| Provider | 1 TB Egress | 10 TB Egress | 100 TB Egress | Notes |
|---|---|---|---|---|
| Amazon S3 | $89 | $872 | $7,536 | First 100 GB/mo free, then $0.09-0.05/GB tiered |
| Google Cloud | $120 | $850 | $8,200 | $0.12/GB premium tier, cheaper standard tier |
| Cloudflare R2 | $0 | $0 | $0 | Zero egress, no conditions |
| Backblaze B2 | $0* | $0* | $10-1,000* | Free up to 3x stored data; free to CDN partners |
| Wasabi | $0** | $0** | Throttled** | Free if download ≤ stored volume |
| DO Spaces | $0 | $92 | $1,008 | 1 TB included in $5/mo plan, then $0.01/GB |
Storage + egress combined for realistic workloads. Assumes 2x egress ratio (download 2x what you store monthly).
| Stored | Amazon S3 | Cloudflare R2 | Backblaze B2 | Wasabi | GCS | DO Spaces |
|---|---|---|---|---|---|---|
| 100 GB | $20 | $1.50 | $0.60 | $6.99 | $26 | $5 |
| 1 TB | $207 | $15 | $6 | $6.99 | $264 | $25 |
| 10 TB | $2,054 | $150 | $60 | $70 | $2,600 | $220 |
| 100 TB | $20,336 | $1,500 | $600 | $699 | $25,800 | $2,020 |
| 1 PB | $203,000 | $15,000 | $6,000 | $6,990 | $258,000 | $20,000 |
Assumes standard storage class + 2x egress ratio. Wasabi fair-use limits may apply. B2 egress free if within 3x stored or using CDN partner. Actual costs depend on request patterns, storage class mix, and region.
Upload and download objects using each provider. All S3-compatible providers use the same AWS SDK — just change the endpoint.
// AWS SDK v3 — Amazon S3
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { readFileSync } from "fs";
const s3 = new S3Client({ region: "us-east-1" });
await s3.send(new PutObjectCommand({
Bucket: "my-bucket",
Key: "photos/sunset.jpg",
Body: readFileSync("./sunset.jpg"),
ContentType: "image/jpeg"
}));
// AWS SDK v3 — Cloudflare R2 (just change endpoint)
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { readFileSync } from "fs";
const r2 = new S3Client({
region: "auto",
endpoint: "https://<ACCOUNT_ID>.r2.cloudflarestorage.com",
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY,
secretAccessKey: process.env.R2_SECRET_KEY
}
});
await r2.send(new PutObjectCommand({
Bucket: "my-bucket",
Key: "photos/sunset.jpg",
Body: readFileSync("./sunset.jpg"),
ContentType: "image/jpeg"
}));
// AWS SDK v3 — Backblaze B2 (S3-compatible endpoint)
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { readFileSync } from "fs";
const b2 = new S3Client({
region: "us-west-004",
endpoint: "https://s3.us-west-004.backblazeb2.com",
credentials: {
accessKeyId: process.env.B2_KEY_ID,
secretAccessKey: process.env.B2_APP_KEY
}
});
await b2.send(new PutObjectCommand({
Bucket: "my-bucket",
Key: "photos/sunset.jpg",
Body: readFileSync("./sunset.jpg"),
ContentType: "image/jpeg"
}));
// AWS SDK v3 — Wasabi (S3-compatible endpoint)
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { readFileSync } from "fs";
const wasabi = new S3Client({
region: "us-east-1",
endpoint: "https://s3.wasabisys.com",
credentials: {
accessKeyId: process.env.WASABI_ACCESS_KEY,
secretAccessKey: process.env.WASABI_SECRET_KEY
}
});
await wasabi.send(new PutObjectCommand({
Bucket: "my-bucket",
Key: "photos/sunset.jpg",
Body: readFileSync("./sunset.jpg"),
ContentType: "image/jpeg"
}));
# Download from S3 using presigned URL
aws s3 presign s3://my-bucket/photos/sunset.jpg --expires-in 3600
# Or direct download with AWS CLI
aws s3 cp s3://my-bucket/photos/sunset.jpg ./sunset.jpg
# R2 presigned URL (uses AWS CLI with custom endpoint)
aws s3 presign s3://my-bucket/photos/sunset.jpg \
--endpoint-url https://ACCOUNT_ID.r2.cloudflarestorage.com \
--expires-in 3600
# Or serve publicly via r2.dev subdomain (zero egress)
curl https://my-bucket.ACCOUNT_ID.r2.dev/photos/sunset.jpg -o sunset.jpg
# B2 download via S3-compatible endpoint
aws s3 cp s3://my-bucket/photos/sunset.jpg ./sunset.jpg \
--endpoint-url https://s3.us-west-004.backblazeb2.com
# Or via friendly URL (if bucket is public)
curl https://f004.backblazeb2.com/file/my-bucket/photos/sunset.jpg -o sunset.jpg
# Works with ANY S3-compatible provider — just change endpoint_url
import boto3
s3 = boto3.client("s3",
endpoint_url="https://ACCOUNT_ID.r2.cloudflarestorage.com", # R2 example
aws_access_key_id="YOUR_KEY",
aws_secret_access_key="YOUR_SECRET"
)
url = s3.generate_presigned_url("put_object",
Params={"Bucket": "uploads", "Key": "user/avatar.png", "ContentType": "image/png"},
ExpiresIn=3600 # 1 hour
)
print(url) # Frontend can PUT directly to this URL
Pair the cheapest storage ($0.006/GB) with free egress through Cloudflare's CDN partnership. B2 waives egress fees for traffic served through Cloudflare.
$0.006/GB/moFree plan$0 egress# Setup: Point Cloudflare DNS to B2 bucket URL
# 1. Create B2 bucket (public) named "my-cdn-bucket"
# 2. In Cloudflare DNS, add CNAME: cdn.example.com -> f004.backblazeb2.com
# 3. Add Transform Rule to rewrite URI: prepend "/file/my-cdn-bucket"
# Result: cdn.example.com/photos/sunset.jpg served via Cloudflare — $0 egress
curl https://cdn.example.com/photos/sunset.jpg
# Served through Cloudflare CDN, B2 egress: $0
When to use a managed provider vs running your own MinIO cluster.
| Factor | Managed (S3, R2, B2, etc.) | Self-Hosted (MinIO) |
|---|---|---|
| Setup Time | Minutes (create account, get keys) | Hours to days (provision servers, configure) |
| Maintenance | Zero — provider handles everything | You handle hardware, updates, monitoring |
| Durability | 11 nines (99.999999999%) guaranteed | Depends on your hardware & erasure coding setup |
| Cost at 10 TB | $60-260/mo (varies by provider) | $50-100/mo (server cost) + your time |
| Cost at 1 PB | $6,000-258,000/mo | Hardware + $96K/yr license (or OSS free) |
| Data Sovereignty | Provider's data centers | Your hardware, your jurisdiction |
| Best For | Most teams, startups, web apps | Regulated industries, air-gapped, petabyte-scale |
Pick the right provider based on your primary constraint.
Backblaze B2 at $0.006/GB/mo. Pair with Cloudflare CDN for free egress. Best for backups, archives, and media that doesn't need global low-latency.
Cloudflare R2 with zero egress fees. If you serve lots of files to users (media, downloads, APIs), R2 saves thousands vs S3/GCS.
Wasabi or DO Spaces. Wasabi: flat $/TB, no request or egress fees. DO Spaces: $5/mo flat with CDN included. No surprise line items.
Amazon S3. Most features, best ecosystem (Lambda, Athena, CloudFront), compliance certifications, 30+ regions. Accept the egress cost for the integrations.
Google Cloud Storage. Deep integration with BigQuery, Vertex AI, and Dataflow. Best if your data pipeline lives on GCP.
MinIO. Self-host on your own hardware. Air-gapped deployments, regulated industries, or anywhere data can't leave your infrastructure.