Access Supabase Storage from Edge Functions
Access Supabase Storage from an Edge Function using `ctx.supabase.storage.from('<bucket_name>')`. Use the `upload()` method to upload a file with parameters: path, file data, and options object containing `contentType`, `cacheControl`, and `upsert` (whether to overwrite existing file). Use `getPublicUrl()` to retrieve the public URL of an uploaded file.
Use serverless-friendly database connections
Treat Postgres as a remote, pooled service in Edge Functions. Use connection pools or serverless-friendly drivers to handle connections efficiently.
Edge Functions support direct Postgres client connections
Because Edge Functions are server-side technology, you can connect directly to your database using any popular Postgres client, such as Deno Postgres driver, and run raw SQL queries.
Use Drizzle with Postgres.js in Edge Functions
You can use Drizzle ORM together with Postgres.js. Both can be loaded directly from npm. Dependencies are declared in a deno.json file inside the function directory.
Edge Functions file storage types
Edge Functions provides two types of file storage: Persistent storage backed by S3 protocol for reading and writing to S3-compatible buckets including Supabase Storage, and Ephemeral storage using the /tmp directory suitable only for temporary operations.
Persistent storage S3 environment variables
To access an S3 bucket from Edge Functions, set these environment variables in Edge Function Secrets: S3FS_ENDPOINT_URL, S3FS_REGION, S3FS_ACCESS_KEY_ID, and S3FS_SECRET_ACCESS_KEY.
Access mounted S3 bucket in Edge Function
To access a file path in a mounted S3 bucket from an Edge Function, use the prefix /s3/YOUR-BUCKET-NAME. For example, to read a file: const data = await Deno.readFile('/s3/my-bucket/results.csv')
Ephemeral storage resets on invocation
Ephemeral storage resets on each function invocation. Files written during an invocation can only be read within the same invocation.
Access ephemeral storage in Edge Functions
Use Deno File System APIs or the node:fs module to access the /tmp path for ephemeral storage in Edge Functions.
Ephemeral storage limits
Ephemeral storage has the following limits: Free projects up to 256MB, Paid projects up to 512MB.
Persistent storage limits
There are no limits on S3 buckets mounted for Persistent storage.
Synchronous File APIs usage restrictions
Synchronous Deno File APIs (statSync, removeSync, writeFileSync, writeTextFileSync, readFileSync, readTextFileSync, mkdirSync, makeTempDirSync, readDirSync) are available only during initial script evaluation and are not supported in callbacks like HTTP handlers or setTimeout. Using them in these contexts will result in a blocklist error.
S3 bucket operations in Edge Functions
In Edge Functions, you can perform POSIX file system operations on mounted S3 buckets including reading files with Deno.readFile(), creating directories with Deno.mkdir(), and writing files with Deno.writeTextFile().
Ephemeral storage with background tasks for large files
Ephemeral storage can be used with Background Tasks to handle large file processing operations that exceed memory limits. Write the file to ephemeral storage first, then use a background task to extract and process it, avoiding memory limit errors.
Storage bucket configuration in config.toml
Configure a storage bucket in supabase/config.toml with the format: [storage.buckets.bucket_name], public = true/false, file_size_limit = "size", allowed_mime_types = ["type/subtype"], objects_path = "./path".
Supabase Storage upload in Edge Function
Upload files to Supabase Storage using ctx.supabaseAdmin.storage.from('bucket_name').upload('path', stream, { contentType: 'mime/type' }).
Creating signed URLs for storage objects
Generate signed URLs for storage objects using ctx.supabaseAdmin.storage.from('bucket_name').createSignedUrl('path', expirySeconds). The returned data contains the signedUrl property.
Supabase Storage provides built-in image transformations
Supabase Storage has out-of-the-box support for common image transformations and optimizations. Edge Functions should be used only for custom image manipulation beyond what Storage provides.
Edge Functions work with Supabase Storage
Edge Functions integrate seamlessly with Supabase Storage, allowing you to upload generated content directly from functions, implement cache-first patterns for performance, and serve files with built-in CDN capabilities.
Use SUPABASE_SECRET_KEYS for server-side storage operations
Server-side storage operations in Edge Functions require the secret key. The secret keys are accessed via Deno.env.get('SUPABASE_SECRET_KEYS'), which returns a JSON object where keys can be referenced by name (e.g., 'default'). Never expose this key in client-side code.
Upload files from Edge Functions example
Example of uploading files from Edge Functions using the Supabase client:
```typescript
import { createClient } from 'npm:@supabase/supabase-js@2'
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
Deno.serve(async (req) => {
const supabaseAdmin = createClient(
Deno.env.get('SUPABASE_URL')!,
// If you want to use a different api key, change 'default' to your preferred key name
SUPABASE_SECRET_KEYS['default']
)
// Generate your content
const fileContent = await generateImage()
// Upload to storage
const { data, error } = await supabaseAdmin.storage
.from('images')
.upload(`generated/${filename}.png`, fileContent.body!, {
contentType: 'image/png',
cacheControl: '3600',
upsert: false,
})
if (error) {
throw error
}
return new Response(JSON.stringify({ path: data.path }))
})
```
Storage upload options
When uploading files to storage, you can specify options including: contentType (MIME type of the file), cacheControl (cache duration in seconds, e.g., '3600' for 1 hour or '86400' for 24 hours), and upsert (boolean to overwrite existing files).
Cache-first pattern for storage
A cache-first pattern checks if a file exists in storage before generating new content. Try fetching the file from storage first using the public storage URL. If it exists (storageResponse.ok is true), return it directly. If it doesn't exist, generate the content, upload it to storage with appropriate cacheControl headers for future requests, and return the generated content.
Cache-first pattern example
Example of implementing a cache-first pattern in Edge Functions:
```typescript
const STORAGE_URL = 'https://your-project.supabase.co/storage/v1/object/public/images'
Deno.serve(async (req) => {
const url = new URL(req.url)
const username = url.searchParams.get('username')
try {
// Try to get existing file from storage first
const storageResponse = await fetch(`${STORAGE_URL}/avatars/${username}.png`)
if (storageResponse.ok) {
// File exists in storage, return it directly
return storageResponse
}
// File doesn't exist, generate it
const generatedImage = await generateAvatar(username)
// Upload to storage for future requests
const { error } = await supabaseAdmin.storage
.from('images')
.upload(`avatars/${username}.png`, generatedImage.body!, {
contentType: 'image/png',
cacheControl: '86400', // Cache for 24 hours
})
if (error) {
console.error('Upload failed:', error)
}
return generatedImage
} catch (error) {
return new Response('Error processing request', { status: 500 })
}
})
```
Public storage URL format
The public storage URL for accessing files follows the format: https://your-project.supabase.co/storage/v1/object/public/bucket-name/file-path