Troubleshooting and Limits
Operating R2 at scale requires an understanding of its hard limits and the nuances of S3 compatibility. When things break, knowing how to trace raw API calls is essential.
R2 Rate Limits
Unlike egress bandwidth, R2 API operations are rate-limited to protect the infrastructure. If your application spikes, you will receive 429 Too Many Requests errors.
| Operation Type | Default Limit | Mitigation Strategy |
|---|---|---|
| Mutating (Class A) (PUT, POST) | 1,000 requests per sec / bucket | Batch uploads, use exponential backoff, or implement jitter in your worker logic. |
| Reading (Class B) (GET) | 10,000 requests per sec / bucket | Place a CDN/Cache in front of the bucket. Hot objects should be served from Cloudflare Edge RAM, never hitting R2 directly. |
S3 Compatibility Gaps
R2 aims for S3 compatibility, but specific AWS features are deliberately omitted or currently unsupported:
- Object Lock (WORM): Write-Once-Read-Many is not natively supported. You cannot enforce absolute immutability policies.
- Bucket Versioning: Supported via API, but considered Beta. Do not rely on it for critical production data recovery yet.
- Granular IAM Policies: AWS S3 allows policies restricting access by IP address, specific prefixes, or time of day. R2 tokens are scoped strictly to the bucket level (Read vs Write).
- AWS EventBridge: R2 Events integrate natively with Cloudflare Queues, not AWS EventBridge or SQS.
Common Error Codes
403 SignatureDoesNotMatch
The cryptographical signature generated by your client tool doesn't match what R2 expects.
- Cause 1: You modified headers (like
Content-Type) on a presigned URL request that were not included in the backend signature generation. - Cause 2: Your AWS CLI is defaulting to
s3v2signatures instead ofs3v4.
400 Bad Request (InvalidEndpoint)
- Cause: You forgot to set
region="auto"in your SDK configuration, or your endpoint URL is missing your Account ID.
403 Access Denied
- Cause: The API Token you are using is scoped to
Bucket A, but your script is trying to upload toBucket B.
Advanced Debugging Techniques
When SDKs hide the underlying network requests, use curl to execute raw REST API calls to isolate the issue.
Tracing AWS CLI Calls
Append --debug to any AWS CLI command to see the raw HTTP headers and response payload. This is the fastest way to debug Signature Mismatches.
r2-awsapi get-object --bucket my-bucket --key file.txt ./output.txt --debug
Look for the Authorization header in the debug output to ensure the Credential string contains your correct Access Key and auto region.
Cloudflare Dashboard Analytics
If you suspect you are hitting rate limits:
- Navigate to your Bucket in the Cloudflare Dashboard.
- Click the Metrics tab.
- Review the 4xx Errors chart. A massive spike in 4xx errors alongside high request volume almost always indicates a
429rate limit block.