# Edge Function memory limit or worker limit errors

> Fix 546 WORKER_RESOURCE_LIMIT errors from SupaHost Edge Functions. Each worker has 150 MB of memory; learn to find what uses it and how to stream and batch instead.

Source: https://supahost.app/kb/function-memory-limit · Updated 2026-11-11

## What you see

The function stops partway through and the caller gets an unusual status code:

```text
HTTP/2 546
sb-error-code: WORKER_RESOURCE_LIMIT
```

546 isn't a standard HTTP status; the runtime uses it to say a worker was stopped for exceeding a resource limit. Older guides call the code `WORKER_LIMIT`. It often happens only for big inputs: a large upload, a long report, or a busy batch.

## Why it happens

Each function request runs in a worker with a **150 MB memory limit**. When the worker goes over, the runtime shuts it down. Common causes:

- Reading a whole file into memory: `await res.arrayBuffer()`, `await blob.text()` or building a PDF or CSV entirely as a string.
- Loading thousands of database rows in one `select()`.
- Heavy npm packages that use a lot of memory just to load (headless browsers, big ML libraries).
- Keeping data in module-level variables that grow with every request the worker serves.

## How to fix it

1. **Confirm it's memory.** In *Dashboard → your project → **Functions** tab → Logs card*, filter to the function. Shutdown events include `memory_mb` and `cpu_ms`, so you can see how close the worker got.
2. **Stream instead of buffering.** Pass bodies through rather than loading them. This proxies a large private file to the caller without holding it in memory:

   ```ts
   import { createClient } from 'npm:@supabase/supabase-js@2'

   const supabase = createClient(
     Deno.env.get('SUPABASE_URL')!,
     Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
   )

   Deno.serve(async (req) => {
     // check the caller is allowed to see this invoice before serving it
     const { data, error } = await supabase.storage
       .from('invoices')
       .createSignedUrl('2026/acme-1042.pdf', 60)
     if (error) return Response.json({ error: error.message }, { status: 400 })

     const file = await fetch(data.signedUrl)
     return new Response(file.body, {
       headers: { 'Content-Type': 'application/pdf' },
     })
   })
   ```

   Often it's simpler still to return the signed URL and let the client download directly.
3. **Page through rows.** Fetch with `.range()` in chunks and process each chunk before fetching the next:

   ```ts
   const pageSize = 500
   for (let from = 0; ; from += pageSize) {
     const { data, error } = await supabase
       .from('orders')
       .select('id,total')
       .range(from, from + pageSize - 1)
     if (error) throw error
     if (!data.length) break
     await handleBatch(data)
   }
   ```

4. **Do aggregation in SQL.** Summing or grouping in Postgres with an RPC call returns a few rows instead of thousands. See [Calling database functions (RPC)](/docs/api/rpc).
5. **Split the work across requests.** Queue items with pgmq and have a scheduled function process a few at a time. See [Processing queue messages](/docs/cron-queues/queue-consumers).
6. **Choose lighter packages,** and import only the submodule you need when a library offers that.

## On SupaHost

Besides the 150 MB per worker, all functions of one project share a container whose memory depends on the plan:

| Plan | Functions container memory |
|---|---|
| Builder | 384 MB |
| Pro | 768 MB |
| Business | 1536 MB |
| Enterprise | 3 GB |

So a few memory-heavy requests running at the same time can press against the container even if each stays under 150 MB. Keeping each request lean helps on both counts. The 150 MB limit per worker is fixed and can't be raised per function.

## Related

- [Edge Function limits](/docs/functions/limits)
- [Edge Function returns 503 or 504](/kb/function-503-504)
- [Logs and debugging](/docs/functions/logs)
- [Using the database from a function](/docs/functions/database-access)
