Edge Function returns 503 or 504

Fix 503 BOOT_ERROR (the function couldn't start) and 504 IDLE_TIMEOUT (no response within 150 seconds) from SupaHost Edge Functions, with the usual causes for each.

What you see

One of these two responses, with the code in the sb-error-code header:

HTTP/2 503
sb-error-code: BOOT_ERROR
HTTP/2 504
sb-error-code: IDLE_TIMEOUT

They have different causes. A 503 happens before your handler runs; a 504 happens after it started but didn't answer in time.

Why it happens

503 BOOT_ERROR: the runtime couldn't start a worker for the function. Something at the top level of the module failed while loading:

  • Code outside Deno.serve that throws, for example new Stripe(Deno.env.get('STRIPE_KEY')!) when the secret is missing, or a top-level await fetch(...) that fails.
  • An import that resolves at deploy time but fails at boot, such as a remote URL that's now unreachable.
  • A module that never calls Deno.serve.

504 IDLE_TIMEOUT: your handler didn't start sending a response within 150 seconds. Typical causes: a slow external API with no timeout, a large batch processed in one request, a slow database query, or a promise that never resolves (for example, a forgotten await on a stream that's never closed).

How to fix a 503

  1. Open Dashboard → your project → Functions tab → Logs card and filter to the function. Boot events and the exception that stopped the boot are logged there.

  2. Move setup that can fail into the handler, or guard it:

    import Stripe from 'npm:stripe@17'
    
    const key = Deno.env.get('STRIPE_SECRET_KEY')
    const stripe = key ? new Stripe(key) : null
    
    Deno.serve(async (req) => {
      if (!stripe) return Response.json({ error: 'Stripe is not configured' }, { status: 500 })
      // ...
      return Response.json({ ok: true })
    })
    
  3. Check that index.ts calls Deno.serve(...).

  4. Pin imports to exact versions (npm:[email protected]) so a new release can't break boot. See Import errors with esm.sh or npm packages.

How to fix a 504

  1. Put timeouts on outbound calls, so a hung API fails fast instead of eating the whole budget:

    const res = await fetch('https://api.example.com/rates', {
      signal: AbortSignal.timeout(10_000),
    })
    
  2. Split big jobs. Process a page of rows per request, or push work onto a queue and let a scheduled function drain it. See Processing queue messages.

  3. Speed up queries the function runs, usually with an index. See Speeding up slow queries with indexes.

  4. Look for hangs. Add console.log checkpoints; the last one in the logs before the timeout shows where it stopped.

On SupaHost

The limits are fixed per function worker: 150 MB of memory, and the response must start within 150 seconds. The dashboard's Test a function panel gives up after 60 seconds, so a slow function can look broken there while it still succeeds when called normally. Test long calls with curl or your app. If the error is 546 instead, see Edge Function memory limit or worker limit errors.

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