infrastructure

R2 File Management

TanStack Ship R2 file management system for Cloudflare object storage, file upload and management, signed URL generation, and audit logging.

File upload to Cloudflare R2 object storage with full audit logging
Admin file browser with search, filter, and file preview
Secure signed URL generation with configurable expiration times
Upload audit history with user attribution and timestamp tracking
Public URL generation for served files and assets
Custom filename and directory organization support
File deletion and lifecycle management
Local development mode with R2 binding mock for offline testing
Also available in:中文·Deutsch

Overview

The R2 file management system in TanStack Ship provides a complete, production-ready solution for handling file uploads and asset storage using Cloudflare R2 serverless object storage. From marketing images and blog media to downloadable resources and user-uploaded content, the system manages the entire file lifecycle — upload, storage, access control, and deletion — with full audit trail capabilities.

As part of the platform, the R2 file management module integrates with the Blog CMS for media storage, the admin dashboard for file management, and URL generation APIs for secure asset delivery. The system supports both public and signed URL access patterns, making it suitable for a wide range of content delivery scenarios.


Design Flow

The R2 file management system orchestrates the complete file lifecycle from upload through storage to access, with audit logging at every stage:


Core Capabilities

File Upload System

Files can be uploaded through multiple channels, each with consistent audit logging:

  • Admin Interface — Upload via the R2 management page with drag-and-drop and bulk upload capabilities
  • API Endpoint — Programmatic upload with multipart form data, supporting authentication and rate limiting
  • Direct Upload — Server-to-server file transfer for backend workflows

Each upload is recorded with complete metadata — file name, size, content type, uploading user, and timestamps — providing a reliable audit trail for billing, compliance, and troubleshooting.

File Management Interface

The admin interface provides comprehensive file management capabilities:

  • File Browser — Browse all uploaded files with thumbnail previews for images and document icons for other formats
  • Search & Filter — Find files by name, date range, uploader, or content type
  • File Preview — View images, PDFs, and text files directly in the browser
  • Bulk Operations — Select and delete multiple files with confirmation safeguards
  • File Details — Inspect metadata including storage location, access URL, upload date, and file hash

URL Generation and Access Control

The system supports multiple URL generation strategies:

  • Public URLs — Direct R2 public bucket URLs for serving images, CSS, and public assets. Ideal for marketing content and blog media.
  • Signed URLs — Time-limited, pre-signed URLs for private file access. Expiration is configurable per request, ensuring sensitive files remain protected while enabling temporary sharing.

Example — Signed URL response:

json
{
  "signedUrl": "https://pub-xxx.r2.dev/file.pdf?X-Amz-Algorithm=...&X-Amz-Expires=3600",
  "expiresIn": 3600,
  "key": "uploads/2025/06/report.pdf"
}

**Example — Fetching a signed URL in React:**

```tsx
import { useQuery } from '@tanstack/react-query'

function SecureDownload({ fileKey }: { fileKey: string }) {
  const { data, isLoading } = useQuery({
    queryKey: ['signed-url', fileKey],
    queryFn: async () => {
      const res = await fetch(`/api/r2/sign/${fileKey}`)
      if (!res.ok) throw new Error('Failed to get signed URL')
      return res.json() as Promise<{ signedUrl: string; expiresIn: number }>
    },
  })

  if (isLoading) return <div>Preparing download...</div>

  return (
    <a href={data?.signedUrl} download>
      Download File
    </a>
  )
}

Design Philosophy

Audit-First Operations

Every file operation — upload, access, deletion — is recorded in the audit log with complete metadata: file name, size, content type, user attribution, and timestamps. This audit-first philosophy means the system provides an immutable record of all file lifecycle events, supporting compliance requirements, billing verification, and operational troubleshooting. The audit table is the source of truth for all file-related activity.

Dual Access Model

The system supports both public and signed URL access patterns for different use cases. Public URLs serve static assets (images, CSS, downloadable resources) with zero overhead, while signed URLs provide time-limited access to private files with configurable expiration. This dual model gives platform operators fine-grained control over asset security — sensitive documents require authentication and expire automatically, while marketing assets are delivered globally via R2's edge network.

Serverless by Default

By building on Cloudflare R2, the file management system inherits serverless benefits: zero egress fees, automatic global distribution via edge caching, and no infrastructure management. Unlike traditional AWS S3 setups that charge per-gigabyte for data transfers, R2 eliminates egress fees entirely while maintaining 100% S3 API compatibility — making it a cost-effective alternative for high-traffic applications, media delivery, and multi-region workloads. Files are stored across Cloudflare's global network and served from the edge node nearest to each user. This architecture eliminates the operational burden of managing file servers and CDN configurations while providing enterprise-grade performance and reliability.


Best Practices

File Size and Type Validation

Configure file size limits and allowed MIME types. Set your desired maximum file size (50MB by default) and restrict upload types to your application's needs to prevent storage exhaustion and block malicious uploads.

Signed URL Expiration Management

Choose expiration times based on your use case: use short durations (5-15 minutes) for one-time downloads of sensitive documents, and longer durations (1-24 hours) for batch processing workflows.

Storage Organization Strategy

Adopt a logical key prefix strategy for organizing files:

  • uploads/{year}/{month}/{uuid}-{name} for user uploads
  • blog/{year}/{slug}/{name} for blog media
  • marketing/{campaign-name}/{name} for marketing assets

This naming convention keeps storage organized, enables efficient listing by prefix, and prevents key collisions.

Regular Audit Review

Periodically review the upload audit table to identify orphaned or unused files. Consider implementing a lifecycle policy that flags files older than a configurable threshold for review.


Frequently Asked Questions

What file types can I upload? Common file types are accepted by default: images (JPEG, PNG, WebP, GIF, SVG), documents (PDF, DOCX, TXT), and media files (MP4, MP3). Allowed MIME types can be extended through configuration.

How do I generate a signed URL for a private file? Request a signed URL through the API with authentication headers. The response includes a pre-signed URL valid for 1 hour by default, with customizable expiration.

Can I organize files into folders? The system uses a flat key-value storage model, but folders can be simulated by using prefix-based key naming (e.g., blog/2024/my-post/image.jpg).

Is there a limit on how many files I can store? Cloudflare R2 has no limit on the number of objects you can store. Be aware of your account's storage quota and set appropriate size limits.

How does the system handle duplicate file names? Each uploaded file receives a unique key, typically incorporating a UUID or timestamp prefix to prevent collisions. The original filename is preserved in metadata for display.

Can I delete files in bulk? Yes. The admin interface supports selecting multiple files and deleting them in a single operation.


Configuration

Configure R2 by setting these environment variables:

R2_BUCKET_NAME=your-bucket
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_PUBLIC_URL=https://pub-xxx.r2.dev
R2_MAX_FILE_SIZE=52428800

The R2 bucket binding must also be configured in the project's wrangler configuration. For local development, a mock mode simulates R2 storage without requiring actual bucket configuration.


Integration Points

The R2 file management system integrates with these platform modules:

  • Blog CMS — Blog post images, cover photos, and media assets are stored and served from R2
  • Admin Dashboard — Full file management interface accessible from the admin panel
  • Marketing Content — Marketing page images, banners, and downloadable resources are distributed through public URLs
  • Email Marketing — Email campaign assets and inline images are hosted on R2
  • User Profiles — Avatar and profile image uploads are stored in per-user key prefixes