Does NestJS Work With Cloudflare R2?

Fully CompatibleLast verified: 2026-02-20

NestJS works seamlessly with Cloudflare R2 using the AWS SDK, enabling enterprise file storage in your backend applications with zero egress costs.

Quick Facts

Compatibility
full
Setup Difficulty
Easy
Official Integration
No — community maintained
Confidence
high
Minimum Versions
NestJS: 9.0.0

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

User-generated content storage (avatars, documents, media uploads) with global CDN distribution
API-based file processing pipelines where egress costs are a concern with high-volume downloads
Multi-tenant SaaS applications needing isolated storage buckets with fine-grained access control
Backup and archival systems for application data with cost-effective unlimited egress

Quick Setup

bash
npm install @nestjs/common @aws-sdk/client-s3
typescript
import { 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

warning

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

critical

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

warning

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