Does NestJS Work With Cloudflare R2?
NestJS works seamlessly with Cloudflare R2 using the AWS SDK, enabling enterprise file storage in your backend applications with zero egress costs.
Quick Facts
How NestJS Works With Cloudflare R2
NestJS integrates with Cloudflare R2 through the AWS SDK for JavaScript (v3), which R2 fully supports as an S3-compatible alternative. You configure the S3Client with R2's endpoint URL and credentials, then use it like any standard S3 bucket—NestJS's modular architecture makes this a natural fit through custom providers or dedicated modules. The developer experience is nearly identical to AWS S3, meaning existing knowledge transfers directly. The main architectural consideration is that R2 operates from Cloudflare's global edge network, so latency is excellent for most geographies and egress is completely free, making it ideal for applications serving files worldwide. Most developers create a dedicated R2Service module that wraps the S3Client, injecting it into controllers that need file operations, keeping concerns cleanly separated.
Best Use Cases
Quick Setup
npm install @nestjs/common @aws-sdk/client-s3import { Injectable } from '@nestjs/common';
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
@Injectable()
export class R2Service {
private s3Client: S3Client;
constructor() {
this.s3Client = 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,
},
});
}
async uploadFile(bucketName: string, key: string, body: Buffer): Promise<void> {
await this.s3Client.send(
new PutObjectCommand({ Bucket: bucketName, Key: key, Body: body })
);
}
async getFile(bucketName: string, key: string): Promise<Buffer> {
const result = await this.s3Client.send(
new GetObjectCommand({ Bucket: bucketName, Key: key })
);
return result.Body?.transformToByteArray() || Buffer.alloc(0);
}
}Known Issues & Gotchas
R2 requires explicit CORS configuration in bucket settings; requests from browsers will fail without it
Fix: Configure CORS rules in the Cloudflare dashboard or via API before making cross-origin requests from frontend code
R2 API tokens and bucket names are separate from AWS credentials; using wrong endpoint or credentials causes 403 errors
Fix: Generate R2 API tokens in Cloudflare dashboard, use the correct endpoint format (https://<account-id>.r2.cloudflarestorage.com), and store credentials in environment variables
S3Client operations are async; forgetting to await calls or improper error handling leads to hanging requests
Fix: Always await S3 operations and wrap in try-catch blocks; implement proper request timeouts in your NestJS interceptors
Alternatives
- •NestJS + AWS S3 (higher egress costs but larger ecosystem and more mature documentation)
- •NestJS + MinIO (self-hosted S3-compatible object storage for full control, requires infrastructure management)
- •NestJS + Google Cloud Storage (different API, strong for Google Cloud-native deployments, typical egress charges apply)
Resources
Related Compatibility Guides
Explore more compatibility guides