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.

What you see

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

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:

    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:

    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).

  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.

  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.

Updated 11 November 2026 · View as Markdown · Something wrong or missing? Tell us