Does Fastify Work With Cloudflare R2?

Fully CompatibleLast verified: 2026-02-26

Yes, Fastify works seamlessly with Cloudflare R2 using the AWS SDK, providing a lightweight, high-performance backend for object storage operations.

Quick Facts

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

How Fastify Works With Cloudflare R2

Fastify integrates with Cloudflare R2 through the AWS SDK for JavaScript (v3), since R2 implements the S3 API. You configure the S3Client with R2's endpoint URL and your Cloudflare credentials, then use it directly in Fastify route handlers. The lightweight nature of Fastify makes it ideal for R2 workloads—there's minimal overhead, fast request handling, and excellent streaming support for large file uploads/downloads. The developer experience is straightforward: install @aws-sdk/client-s3, initialize the client with R2 credentials, and use familiar S3 operations (putObject, getObject, etc.) in your Fastify routes. No custom middleware or plugins are needed. The combination shines for building APIs that handle file uploads, serve static assets, or manage media libraries without egress costs.

Best Use Cases

Building a file upload API that stores user-generated content with zero egress fees
Creating a lightweight asset CDN origin that Cloudflare Workers can cache and serve globally
Processing and storing image/video uploads with real-time Fastify handlers
Building a document management system with signed R2 URLs for direct client downloads

Quick Setup

bash
npm install fastify @aws-sdk/client-s3
typescript
import Fastify from 'fastify';
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';

const fastify = Fastify();
const s3 = new S3Client({
  region: 'auto',
  endpoint: 'https://<account-id>.r2.cloudflarestorage.com',
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID!,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
  },
});

fastify.post<{ Body: { file: Buffer } }>('/upload', async (request, reply) => {
  const data = await request.file();
  const buffer = await data.toBuffer();
  await s3.send(new PutObjectCommand({
    Bucket: 'my-bucket',
    Key: data.filename,
    Body: buffer,
  }));
  reply.send({ ok: true });
});

fastify.get<{ Params: { key: string } }>('/files/:key', async (request, reply) => {
  const result = await s3.send(new GetObjectCommand({
    Bucket: 'my-bucket',
    Key: request.params.key,
  }));
  reply.type('application/octet-stream').send(result.Body);
});

fastify.listen({ port: 3000 });

Known Issues & Gotchas

warning

Multipart uploads fail silently if credentials lack necessary R2 permissions

Fix: Ensure your Cloudflare API token has 'Object Read & Write' permissions for R2. Test credentials early in development.

info

R2 API calls from outside Cloudflare's network may have higher latency than S3

Fix: For latency-sensitive operations, consider using Cloudflare Workers instead of external Fastify servers. Deploy Fastify close to your users or use Workers as middleware.

warning

AWS SDK v3 has large bundle size; tree-shaking is essential

Fix: Import only needed commands (e.g., 'PutObjectCommand') rather than the full client to reduce bundle size in serverless contexts.

Alternatives

  • Express.js + AWS SDK v3 (more verbose, heavier framework than Fastify)
  • Cloudflare Workers + R2 (serverless, native integration, but different programming model)
  • Node.js native http module + minio (lighter than Fastify, S3-compatible client library)

Resources

Related Compatibility Guides

Explore more compatibility guides