Files
supabase/apps/docs/content/guides/functions/ephemeral-storage.mdx
Chris ChinchillaandKalleby Santos b6dba956ef docs: Functions Key changes (#45224)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Replaced legacy "Anon"/"Service Role" key terminology with
"Publishable Keys" and "Secret Keys" across Edge Functions guides
* Updated authentication examples and request headers (client-side vs
server-side) to reflect publishable/secret key usage
* Standardized environment-variable examples to use parsed secret-key
maps with a selectable default
* Removed guidance for bypassing JWT verification via the deprecated CLI
flag
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Kalleby Santos <kalleby_santos@hotmail.com>
2026-04-29 11:12:54 +00:00

199 lines
6.3 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: 'function-ephemeral-storage'
title: 'File Storage'
description: 'Use persistent and ephemeral file storage'
subtitle: 'Use persistent and ephemeral file storage'
---
Edge Functions provides two flavors of file storage:
- Persistent - backed by S3 protocol, can read/write from any S3 compatible bucket, including Supabase Storage
- Ephemeral - You can read and write files to the `/tmp` directory. Only suitable for temporary operations
You can use file storage to:
- Handle complex file transformations and workflows
- Do data migrations between projects
- Process user uploaded files and store them
- Unzip archives and process contents before saving to database
---
## Persistent Storage
The persistent storage option is built on top of the S3 protocol. It allows you to mount any S3-compatible bucket, including Supabase Storage Buckets, as a directory for your Edge Functions.
You can perform operations such as reading and writing files to the mounted buckets as you would in a POSIX file system.
To access an S3 bucket from Edge Functions, you must set the following for environment variables in Edge Function Secrets.
- `S3FS_ENDPOINT_URL`
- `S3FS_REGION`
- `S3FS_ACCESS_KEY_ID`
- `S3FS_SECRET_ACCESS_KEY`
[Follow this guide](/docs/guides/storage/s3/authentication) to enable and create an access key for Supabase Storage S3.
To access a file path in your mounted bucket from your Edge Function, use the prefix `/s3/YOUR-BUCKET-NAME`.
```tsx
// read from S3 bucket
const data = await Deno.readFile('/s3/my-bucket/results.csv')
// make a directory
await Deno.mkdir('/s3/my-bucket/sub-dir')
// write to S3 bucket
await Deno.writeTextFile('/s3/my-bucket/demo.txt', 'hello world')
```
## Ephemeral storage
Ephemeral storage will reset on each function invocation. This means the files you write during an invocation can only be read within the same invocation.
You can use [Deno File System APIs](https://docs.deno.com/api/deno/file-system) or the [`node:fs`](https://docs.deno.com/api/node/fs/) module to access the `/tmp` path.
```tsx
Deno.serve(async (req) => {
if (req.headers.get('content-type') !== 'application/zip') {
return new Response('file must be a zip file', {
status: 400,
})
}
const uploadId = crypto.randomUUID()
await Deno.writeFile('/tmp/' + uploadId, req.body)
// E.g. extract and process the zip file
const zipFile = await Deno.readFile('/tmp/' + uploadId)
// You could use a zip library to extract contents
const extracted = await extractZip(zipFile)
// Or process the file directly
console.log(`Processing zip file: ${uploadId}, size: ${zipFile.length} bytes`)
})
```
---
## Common use cases
### Archive processing with background tasks
You can use ephemeral storage with [Background Tasks](/docs/guides/functions/background-tasks) to handle large file processing operations that exceed memory limits.
Imagine you have a Photo Album application that accepts photo uploads as zip files. A streaming implementation will run into memory limit errors with zip files exceeding 100MB, as it retains all archive files in memory simultaneously.
You can write the zip file to ephemeral storage first, then use a background task to extract and upload files to Supabase Storage. This way, you only read parts of the zip file to the memory.
```tsx
import { BlobWriter, ZipReader } from 'https://deno.land/x/zipjs/index.js'
import { createClient } from 'jsr:@supabase/supabase-js@2'
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
// If you want to use a different api key, change 'default' to your preferred key name
const supabase = createClient(Deno.env.get('SUPABASE_URL')!, SUPABASE_SECRET_KEYS['default'])
async function processZipFile(uploadId: string, filepath: string) {
const file = await Deno.open(filepath, { read: true })
const zipReader = new ZipReader(file.readable)
const entries = await zipReader.getEntries()
await supabase.storage.createBucket(uploadId, { public: false })
await Promise.all(
entries.map(async (entry) => {
if (entry.directory) return
// Read file entry from temp storage
const blobWriter = new BlobWriter()
const blob = await entry.getData(blobWriter)
// Upload to permanent storage
await supabase.storage.from(uploadId).upload(entry.filename, blob)
console.log('uploaded', entry.filename)
})
)
await zipReader.close()
}
Deno.serve(async (req) => {
const uploadId = crypto.randomUUID()
const filepath = `/tmp/${uploadId}.zip`
// Write zip to ephemeral storage
await Deno.writeFile(filepath, req.body)
// Process in background to avoid memory limits
EdgeRuntime.waitUntil(processZipFile(uploadId, filepath))
return new Response(JSON.stringify({ uploadId }), {
headers: { 'Content-Type': 'application/json' },
})
})
```
### Image manipulation
Custom image manipulation workflows using [`magick-wasm`](/docs/guides/functions/examples/image-manipulation).
```tsx
Deno.serve(async (req) => {
// Save uploaded image to temp storage
const imagePath = `/tmp/input-${crypto.randomUUID()}.jpg`
await Deno.writeFile(imagePath, req.body)
// Process image with magick-wasm
const processedPath = `/tmp/output-${crypto.randomUUID()}.jpg`
// ... image manipulation logic
// Read processed image and return
const processedImage = await Deno.readFile(processedPath)
return new Response(processedImage, {
headers: { 'Content-Type': 'image/jpeg' },
})
})
```
---
## Using synchronous file APIs
You can safely use the following synchronous Deno APIs (and their Node counterparts) _during initial script evaluation_:
- Deno.statSync
- Deno.removeSync
- Deno.writeFileSync
- Deno.writeTextFileSync
- Deno.readFileSync
- Deno.readTextFileSync
- Deno.mkdirSync
- Deno.makeTempDirSync
- Deno.readDirSync
**Keep in mind** that the sync APIs are available only during initial script evaluation and aren’t supported in callbacks like HTTP handlers or `setTimeout`.
```tsx
Deno.statSync('...') // ✅
setTimeout(() => {
Deno.statSync('...') // 💣 ERROR! Deno.statSync is blocklisted on the current context
})
Deno.serve(() => {
Deno.statSync('...') // 💣 ERROR! Deno.statSync is blocklisted on the current context
})
```
---
## Limits
There are no limits on S3 buckets you mount for Persistent storage.
Ephemeral Storage:
- Free projects: Up to 256MB of ephemeral storage
- Paid projects: Up to 512MB of ephemeral storage