Documentation
Storage

Overview

Configure and use S3-backed file uploads with presigned URLs.

AI Skill for storage

Prompt: Type /storage in your Copilot / Cursor or other chat to use skill with the provided context.
/storage Add file upload for [describe entity/form].

Use cases: What to store in S3

Instead of saving files directly to your application server (which is anti-pattern in modern scalable apps), GoLiveKit is configured to upload files directly into an S3-compatible service. Common use cases include:

  • User Avatars: Profile pictures and company logos.
  • Documents & Attachments: PDFs, CSVs, or other user-submitted files.
  • Media: Images hosted for blog posts, e-commerce products, or user generated content.

Direct-to-S3 Uploads

GoLiveKit uploads files straight from the browser to the S3 bucket using presigned URLs. This offloads entirely the upload bandwidth from your Node.js application server.

Required Environment Variables

You need to set up credentials for any S3-compatible object storage provider.

.env
S3_REGION=auto
S3_BUCKET=your-bucket-name
S3_ACCESS_KEY_ID=your-copied-access-key-id
S3_SECRET_ACCESS_KEY=your-copied-secret-access-key
S3_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
.env
S3_REGION=us-east-1
S3_BUCKET=your-bucket
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
# S3_ENDPOINT is not required for AWS S3

App Configuration

Common storage defaults are defined in src/config/app.ts under APP_CONFIG.files.storage. These are the global safety limits:

  • keyPrefix: The folder path prefix where files are stored inside your bucket.
  • presignedUrlExpiresInSeconds: How long the upload URL remains valid.
  • maxFileSizeBytes: The maximum allowed size for uploaded files globally.
  • maxFilesCount: The overall file limit per upload batch.
  • acceptedTypes: Global accept rules (like image/*,application/pdf).

Note: Per-field upload settings from specific forms can restrict uploads further, but can never exceed these global maximum thresholds.

The Upload Flow (API Endpoints)

The application uses a 3-step direct-to-S3 approach:

Request presigned URL

The client hits the oRPC endpoint (POST /api/v1/files/create-presigned-upload-url) to get a secure upload target.

Upload directly

The client uploads file bytes straight to S3 via PUT request without touching your server.

Finalize

The client calls POST /api/v1/files/finalize-upload to register the new file record in your postgres database for later use.

Note: If the upload request is authenticated, the userId is automatically attached to the resulting file metadata.

UI Integration

To implement file uploading in your React views or forms, you can use the built-in <FileDropzone /> component. This handles the entire S3 orchestration behind the scenes.

src/features/your-feature/components/my-form.tsx
import { useState } from 'react';
import { FileDropzone } from '@/features/common/files/components/file-dropzone';
import type { UploadedFile } from '@/features/common/files/model/files.schema';

export function AvatarUploader() {
  const [files, setFiles] = useState<UploadedFile[]>([]);

  return (
    <div className="max-w-md">
      <FileDropzone
        value={files}
        onChange={setFiles}
        view="image" // Use "file" for general attachments or "image" for image previews
        maxFilesCount={1}
        maxFileSizeBytes={5_000_000} // Override locally (up to max global limit)
        acceptedTypes={['image/jpeg', 'image/png']}
      />
      
      {files.length > 0 && (
        <p className="mt-2 text-sm text-muted-foreground">
          Uploaded File ID: {files[0].id}
        </p>
      )}
    </div>
  );
}

On this page