Does Django Work With Cloudflare R2?
Django works seamlessly with Cloudflare R2 for file storage using boto3 and django-storages, enabling S3-compatible object storage without egress costs.
Quick Facts
How Django Works With Cloudflare R2
Django doesn't natively support R2, but the ecosystem makes integration trivial through django-storages and boto3. Django-storages is a popular third-party package that provides a pluggable storage backend system, allowing you to swap the default filesystem storage for S3-compatible services like R2. Since R2 implements the S3 API, you configure it as an S3 backend with R2's endpoint URL instead of AWS.
The developer experience is excellent—you configure credentials in Django settings, and Django handles all file operations (uploads, downloads, deletions) through the storage abstraction layer. This means your models, views, and forms require zero changes. The primary architectural benefit is that R2's zero egress fees make it ideal for high-traffic applications serving media files, CDN-backed content, or large user uploads without cost surprises. Your application stays stateless since files live remotely, enabling easy horizontal scaling.
One consideration: R2 has eventual consistency for some operations and a 24-hour object immutability window, which are rarely issues but worth noting for critical use cases. Most Django projects see this as a straightforward, cost-effective replacement for AWS S3.
Best Use Cases
Quick Setup
pip install django-storages boto3# settings.py
import os
# Configure R2 as default storage backend
STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'
DEFAULT_FILE_STORAGE = STORAGE_BACKEND
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
# R2 credentials and endpoint
AWS_ACCESS_KEY_ID = os.getenv('R2_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('R2_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = 'my-django-bucket'
AWS_S3_REGION_NAME = 'auto' # R2 uses 'auto'
AWS_S3_ENDPOINT_URL = 'https://<account-id>.r2.cloudflarestorage.com'
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.cdn.example.com' # Optional: use Cloudflare CDN
AWS_S3_USE_SSL = True
AWS_QUERYSTRING_AUTH = False
# models.py
from django.db import models
class Document(models.Model):
title = models.CharField(max_length=200)
file = models.FileField(upload_to='documents/')
# Files automatically store in R2, no code changes needed!Known Issues & Gotchas
django-storages S3 backend may cache bucket region, causing 'IllegalLocationConstraintException' errors on first deploy
Fix: Explicitly set AWS_S3_REGION_NAME and AWS_S3_ENDPOINT_URL in settings to match your R2 bucket region
Default CORS settings on R2 buckets are restrictive; browser-based uploads fail without proper CORS configuration
Fix: Configure CORS rules in the Cloudflare dashboard or use boto3 to set bucket policies allowing your domain
Signed URLs expire and may not work as expected if R2 account lacks proper token permissions
Fix: Use R2 API tokens with object.read and object.write scopes; test signed URL generation in development
Large file uploads (>100MB) may timeout without proper multipart upload configuration
Fix: Configure AWS_S3_MAX_MEMORY_SIZE and enable multipart uploads in django-storages settings
Alternatives
- •AWS S3 with django-storages (more expensive egress, more AWS service integrations)
- •Azure Blob Storage with django-storages (good for Microsoft-heavy ecosystems)
- •MinIO self-hosted S3-compatible storage (full control, requires infrastructure management)
Resources
Related Compatibility Guides
Explore more compatibility guides