A New Hope for Object Storage: R2 Enters Open Beta
blog.cloudflare.com
blog.cloudflare.com
I haven't been able to get either working:
const s3Client = new S3Client({
endpoint: 'https://my-account-id.r2.cloudflarestorage.com',
credentials: secrets.r2Credentials,
})
await s3Client.send(
new PutObjectCommand({
Bucket: 'my-bucket,
Key: 'test',
Body: JSON.stringify({hello: 'world'}),
}),
)
^ This fails with a 500 const r2Client = new AwsClient({
...secrets.r2Credentials,
})
fetch(
await r2Client.sign(
'https://my-account-id.r2.cloudflarestorage.com/' +
'?Key=test&Bucket=my-bucket',
{
method: 'put',
body: JSON.stringify({ hello: 'world' }),
},
),
).then((response) => console.log(response.status))
^ This fails with 401I've verified that the key has full access and even rerolled it to make sure I didn't mess up the copy paste, but still no luck.
Any ideas where I could be going wrong?
I think you need to set s3ForcePathStyle to true for the first example (or however you do it in the v3 version of the SDK[2]). For the latter, we don't support pre-signed requests. Feel free to ask on discord [3] too. Might get more timely responses.
[1] https://developers.cloudflare.com/r2/examples
[2] https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clien...
For SDK v3, I just needed to add the forcePathStyle flag.
For aws4fetch (note that this isn't a presigned request, it's just signing the request for Sig V4 like the official SDK would), I needed to change the fetch url to https://my-account-id.r2.cloudflarestorage.com/my-bucket/key.
This will reduce our monthly S3 charge from tens-of-thousands USD per month, to ~$200.
https://www.cloudflare.com/supplemental-terms/#cloudflare-de...
Thats the major problem of the CDN product, they dont say that are no traffic fee, they just say they will not charge you "except" on some cases (that you never know). But other products they are very specific of the egress fee, like Stream, Magic Transit, Spectrum, etc.... They should fix that matter on CND, no one like that.
Sure, i dont know what will happen if someone just try to make a youtube like over R2... They probable "want" that....
Is that still on the cards?
[1] https://developers.cloudflare.com/r2/platform/s3-compatibili...
1a. Cloudflare Cache is free for users (up to 500MB per file for unlimited files), but if R2 uses it transparently, are reads from cache metered per R2 pricing? And what about the file-size limits that apply to free/pro accounts?
1b. How is strong-consistency guaranteed despite caches in front of the bucket? I guess cache-invalidation can be done through Durable Object (DO) Alarms or some such? Or, would this guarantee no longer hold?
2. TFA mentions in the passing that R2 utilizes DO (for presumably metadata / journal?). Cloudflare once wrote in detail about how DO is used in a pretty novel way to power wrangler tail, and so I was wondering if there's something novel about R2's use of DO, too?
3. In-Worker API: Are customers metered for both In-Worker API (duration and invocation) and R2 (Class A / Class B)? If so, that makes Class B operations almost twice as expensive than S3 (excluding egress).
4. Any ETA on "Public buckets"?
5. Has Cloudflare rolled out newer server designs just for R2 (aka Dropbox's MagicPocket)?
6. Is serving media content (say, audio and video) an acceptable use-case for R2?
7. Any plans for Kinesis Firehose (a managed-ingestion pipeline) esque product to front R2?
Thanks.
1b. Unavoidably as you guess you'd be giving up the consistency. Presumably the consistency guarantees would be part of the cache-control header you associate with the object. Cache purging would probably work similar & we have exciting upcoming news about major performance improvements for that. But again, since we don't have any idea of what that product looks like, hard to say.
2. There is. I have a bunch of technical blog posts written but we decided to punt on providing that detail for a few months just to give everyone some breathing room. R2 does have one important extension we got the DO team to build just for us (not 1 instance of the code instantiated). That piece will only be available for R2. R2 is also driving performance improvements & API improvements to DO that will almost certainly percolate out to external users.
3. The equivalent model would be AWS Lambda + S3 so I think we're significantly cheaper (+ Workers is faster than AWS lambda - R2 is still in open beta so not useful to compare perf against S3 yet). Yes, if you're using it to emulate public buckets, then it'll be a bit expensive (depending on egress charges you might otherwise face)
4. Soon. It's very high on our list alongside pre-signed URLs
5. Nothing to share at this time.
6. Yes. From Matthew Prince aka eastdakota [1]
7. Nothing to share at this time.
1. Are the rate limits for all users on a given bucket, or by source IP as some other providers do?
2. What is the plan for the rate limits post beta?
3. Do you support the x-amz-content-sha256 header. i.e. If a put contains that header and the content hash doesn't match is it rejected?
4. What does it mean to support pre-signed URLs? Can't a client pre-sign a URL that anyone else can use? My understanding is they are the same as normal usage from the server's perspective, just the key holder signs the request, and the other person actually makes the request.
5. Why is the read limit smaller than the write limit?
1 & 2 - We're reserving some ability to rate-limit during beta as we figure out how best to scale our systems under load. I'll defer to vlovich & greg-m for post-beta plans.
3. We do support that header. Mismatching content hashes will be rejected during write. If you ever experience otherwise, please report it.
4. We only support sigv4 auth via header currently: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-u...
With presigned urls, we will support sigv4 in url parameters https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-...
5. See #1. We'll be improving the throughput of both operations, but currently reads have higher throughput than writes.
So presigned URLs that use auth header are fine (We use those extensively in Peergos, as presigned with an auth query parameter isn't cached by browsers as the query string will change with subsequent requests).
When using the "free" cache product, solving this is Cloudflare's problem - they have a lot of incentives to stop people from being able to do that as it would otherwise cost them money.
However, when using the R2 product, Cloudflare sure would be incentivized to do whatever they can to make all these requests succeed so they can bill you for them.
Before someone tries bringing up their rate limiting product, that is more than an order of magnitude more expensive than R2.
Putting cache in front of public buckets is also something you’ll be able to do.
Rate limiting is very similar to spending limits and, at the scale you’re talking about, they’re just expressing the same concept from different perspectives. R2 is currently naturally rate limited anyway because we can’t go faster but that will obviously evolve as we improve the system. Additionally, you can’t currently have public buckets (at least not without exposing it through a Worker you write). The main use for rate limiting and spending limits is more about being OK choosing to have an outage because of a spike in load (e.g. your project going viral unexpectedly on HN before you’ve cost-optimized it for that kind of scale).
From a motivation/incentives perspective, Cloudflare is a SaaS company focusing on security and trust. We’re never incentivized to have unhappy customers, no matter how big of a bill we can deliver for any given month. Doubly so when that comes because you’re under attack vs you’re having success.
So TLDR:
1. Bot fight mode is probably useful as a DOS mitigation tool when hosting a public bucket.
2. When we add virtual pathing, buckets are hosted under your account domain. Unlike with other providers, people can’t scrape public records to find what buckets you’ve exposed (intentionally or otherwise) to the public.
3. The product is currently naturally rate limited.
4. Rate limiting isn’t a viable solution here because an outage is not meaningfully better from us charging you insane amounts of month for that month. If you get an unexpectedly large bill, please reach out to Cloudflare support.
5. Public buckets don’t actually exist yet.
6. Cloudflare is in the business of security and trust and we’re incentivized to do our best to engender that trust.
Does that speak to your concerns?
I have some more thoughts on those:
- Will adding the cache in front of a public bucket come with the necessary ToS updates to allow serving the media content in the bucket?
- It would be nice if there could be some kind of timed authorization for downloads (like a signed token in a header or something?) that does not count towards class B charges if it fails. Currently you can implement this with a worker, but it actually still causes a charge to run the worker, so is mostly ineffective.
> that does not count towards class B charges if it fails
What does failure mean in this context?
Something like this would really help cutting down on unwanted bot requests as each valid request could be traced back to a user and abusive users could be banned.
But if the "failed" requests still cause a charge on your account, this wouldn't really work as intended.
Just trying to think of reliable ways to defend against bot downloading causing massive charges, but also without letting them take down the entire site by triggering something like a billing cap. Hostile world out there...
I think the solution is bot fight protection services from Cloudflare. There's a bunch in there also to allow well-behaved bots to have access and lets you control what those look like.
cl = boto3.client(
's3',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
endpoint_url=endpoint,
config=Config(
region_name = endpoints[endpoint_name].get('region', 'auto'),
s3={'addressing_style': 'path'},
retries=dict( max_attempts=0 ),
),
)
dict "endpoints" is undefined in the example code above, replace that line with: region_name = 'auto',
----While,
an S3-compatible API, which exposes your bucket on a URL of the form bucket.account.r2storage.com.
Should be? an S3-compatible API, which exposes your bucket on a URL of the form account.r2.cloudflarestorage.com/bucketWe’re fixing the blog post.