Back to Resources
Supabase

Supabase Storage Optimization: CDN, Access Policies, and Cost Management

BI
Bilal Nazam
April 1, 20256 min read

Supabase Storage Basics

Supabase Storage is built on top of S3-compatible object storage with a built-in CDN. It integrates directly with your RLS policies, handles image transformations, and provides both public and private file access. But the default setup isn't always optimal — here's how to get the most out of it.

1. Choose the Right Bucket Type

Supabase has two bucket types with very different behaviors:

  • Public buckets: Files accessible to anyone with the URL. Good for: avatars, blog images, product photos, anything SEO-relevant.
  • Private buckets: Files require signed URLs. Good for: user documents, invoices, private media.
-- Create a public bucket for avatars
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);

-- Create a private bucket for documents
INSERT INTO storage.buckets (id, name, public)
VALUES ('documents', 'documents', false);

2. Set Up Storage RLS Policies

-- Users can upload to their own folder
CREATE POLICY "user_upload_avatar" ON storage.objects FOR INSERT
  WITH CHECK (
    bucket_id = 'avatars'
    AND (storage.foldername(name))[1] = auth.uid()::text
  );

-- Users can update/delete their own files
CREATE POLICY "user_manage_own_files" ON storage.objects FOR ALL
  USING (
    bucket_id = 'avatars'
    AND (storage.foldername(name))[1] = auth.uid()::text
  );

3. Use Image Transformations

Supabase Storage can resize and optimize images on-the-fly. Always serve appropriately sized images instead of full-resolution originals:

// Get a resized, cached image URL
const { data } = supabase.storage
  .from('avatars')
  .getPublicUrl('user123/avatar.jpg', {
    transform: {
      width: 200,
      height: 200,
      resize: 'cover',
      quality: 80
    }
  })

// Returns a URL with automatic resizing
// Transformed images are cached by the CDN

4. Generate Signed URLs for Private Files

// Generate a signed URL valid for 1 hour
const { data, error } = await supabase.storage
  .from('documents')
  .createSignedUrl('reports/q4-2024.pdf', 3600)

// For multiple files at once (more efficient)
const { data } = await supabase.storage
  .from('documents')
  .createSignedUrls([
    'invoice-001.pdf',
    'invoice-002.pdf'
  ], 3600)

5. Upload Optimization

// Upload with progress tracking
const { data, error } = await supabase.storage
  .from('uploads')
  .upload(filePath, file, {
    contentType: file.type,
    upsert: false, // Prevent accidental overwrites
    duplex: 'half' // For streaming uploads
  })

// For large files, use resumable uploads
const { data } = await supabase.storage
  .from('videos')
  .uploadToSignedUrl(path, token, file)

6. Organize Files for CDN Efficiency

Structure your file paths to take advantage of CDN caching:

// Good: organized by type and user
avatars/{userId}/profile.jpg
documents/{userId}/{year}/{filename}
products/{productId}/images/{index}.jpg

// Bad: flat structure that's hard to manage
{randomUUID}.jpg

7. Cost Management

Storage costs come from two sources: storage space and egress (bandwidth). Manage both:

  • Delete files when users delete accounts (use database triggers or cleanup functions)
  • Compress images before upload on the client side
  • Use image transformations to avoid storing multiple sizes
  • Set up lifecycle policies to auto-delete temporary files
// Client-side image compression before upload
async function compressImage(file: File): Promise {
  // Use browser-image-compression library
  const options = { maxSizeMB: 1, maxWidthOrHeight: 1920 }
  return await imageCompression(file, options)
}

Categorized In

supabasestoragecdnoptimizationfiles

Frequently Asked Questions

Does Supabase Storage have a CDN?

Yes. Public bucket files are served through a global CDN automatically. Transformed images are also cached at the CDN layer.

How do I migrate files from another storage provider to Supabase Storage?

Download files from your current provider and upload them to Supabase Storage using the admin client. For large migrations, process files in batches to avoid rate limits.

Can I use Supabase Storage with a custom domain?

On Supabase Cloud Pro and above, you can configure custom domains. For self-hosted Supabase, configure Nginx to proxy storage requests through your domain.

Share This Intelligence

Start Your Migration Strategy

Don't let vendor lock-in stifle your growth. Get a professional roadmap to Supabase excellence today.

Free Architectural Audit