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

Source: https://supahost.app/kb/function-503-504 · Updated 2026-11-11

## What you see

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

```text
HTTP/2 503
sb-error-code: BOOT_ERROR
```

```text
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:

   ```ts
   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:stripe@17.5.0`) so a new release can't break boot. See [Import errors with esm.sh or npm packages](/kb/esm-sh-imports).

## How to fix a 504

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

   ```ts
   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](/docs/cron-queues/queue-consumers).
3. **Speed up queries** the function runs, usually with an index. See [Speeding up slow queries with indexes](/kb/improve-query-performance).
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](/kb/function-memory-limit).

## Related

- [Edge Function limits](/docs/functions/limits)
- [Edge Function takes too long or times out](/kb/function-timeout)
- [Logs and debugging](/docs/functions/logs)
- [Edge Function returns 500](/kb/function-500)
