A Supabase Edge Function that returns 504 Gateway Timeout is not automatically a sign that Supabase is too slow or that you need a bigger plan.
It means you need to find which part of the request consumed the time.
Supabase’s current Edge Function limits say a function must begin a response within a 150-second request idle timeout. Its troubleshooting documentation points to common causes including slow external APIs, inefficient database queries, large dependencies, CPU-heavy work and cold starts.
The useful debugging question is therefore not “how do I make the timeout longer?” It is:
Should this work finish inside one HTTP request at all?
That distinction matters especially in AI-built products. It is easy to ask an agent to “fix the timeout” and end up with more retries, longer polling or duplicated operations while the underlying architecture stays wrong.
First map the request path
Write the operation as a chain:
client → Edge Function → authentication → database reads → external services → database writes → response
Then add timing around each boundary.
If the request spends 120 seconds waiting for an external API, rewriting your SQL will not solve the real problem. If 100 records are processed one after another, changing the frontend spinner will not solve it either.
Supabase recommends checking Function logs and boot events first, then looking for slow dependencies, API calls, computation and queries. See the current Edge Function timeout troubleshooting guide.
Know which limit you are actually hitting
The hosted platform currently documents several different limits, including a 150-second request idle timeout, a worker wall-clock lifetime and a CPU-time limit. They describe different things.
The 504 troubleshooting page is particularly important: an internal 504 means the function failed to initiate a response within the 150-second request window. Supabase says this request idle limit cannot currently be increased.
See Supabase Edge Function limits and its 504 troubleshooting documentation.
Do not design around a number copied from an old tutorial. Platform limits change.
Check for serial work before changing architecture
A common pattern looks harmless:
- fetch 100 records;
- loop through them;
- call another service for record one;
- wait;
- write its result;
- repeat 99 more times;
- return only when everything is finished.
That turns small pieces of latency into one long request.
Before moving everything to a queue, check whether independent I/O can safely run concurrently, whether one database operation can replace dozens of round trips, whether you are selecting more data than needed, and whether the external service supports batching.
But concurrency is not a magic fix either. Sending 100 requests at once can hit rate limits or create a different failure mode.
Separate user response time from job completion time
Some operations simply should not keep the browser waiting.
Imports, report generation, bulk notifications, large media processing and multi-step AI jobs are examples where a better flow may be:
request accepted → job created → quick response with job ID → worker processes job → status stored → client checks/subscribes → result becomes available
Now the product has two explicit states: the request was accepted and the work completed.
That is much easier to reason about than a spinner attached to a request that may time out while downstream work is still happening.
Supabase supports background tasks for work that can continue after a response, but those tasks still live within the platform’s worker limits. For jobs that can exceed those limits or require robust retry/rate-control behaviour, design a proper durable job boundary rather than assuming background execution makes a task unlimited.
Do not add retries until the operation is idempotent
This is the production trap I care about most.
Imagine the function:
- creates a payment record;
- sends an email;
- updates an entitlement;
- then times out before the client sees success.
The user presses Retry.
If the operation has no idempotency protection, you can now have two emails, duplicate rows or repeated external side effects.
A timeout is therefore not just a performance problem. It can become a state-integrity problem.
Before enabling automatic retries, decide what uniquely identifies the operation, what “already completed” means, which steps are safe to repeat, and how partial failure is recorded.
That same principle appears in payment systems, imports, booking flows and webhook processing: retries should converge on the correct state rather than duplicate it.
When the database is the bottleneck
Do not fetch an entire table into an Edge Function merely to perform work PostgreSQL can express directly.
Supabase’s troubleshooting guidance recommends selecting only required columns and limiting results instead of broad select('*') queries on large tables.
For multi-row state changes, consider whether a database function or transaction can perform the operation closer to the data and atomically. Keep privileged operations server-side and preserve your RLS/auth model rather than bypassing security to gain speed.
If the problem is actually an RLS policy loop rather than latency, use my Supabase RLS infinite recursion guide. If the function returns 401 before your code behaves as expected, use the Edge Function 401 guide.
A practical timeout debugging sequence
Before changing the architecture, capture one failing request and answer these questions:
| Question | What it tells you |
|---|---|
| Did the function boot normally? | Whether startup/dependencies deserve attention. |
| How long did each database call take? | Whether query shape or round trips dominate. |
| How long did each external API call take? | Whether the bottleneck is outside Supabase. |
| Is work performed serially in a loop? | Whether latency is being multiplied. |
| Did any side effect complete before timeout? | Whether retries can corrupt state. |
| Does the job genuinely need more than one request window? | Whether it belongs behind a job boundary. |
Only then choose between optimisation and redesign.
For AI-built apps, ask the agent for evidence
Do not prompt:
Fix my Supabase timeout.
Give the agent the failing invocation timestamp, status code, function logs, timing around major calls, approximate input size, external services involved and whether retries have already caused duplicate work.
Then ask it to identify the first boundary that consumes unexpected time and propose the smallest safe change.
That is the same production discipline behind my AI-built app production checklist: AI can generate the code quickly, but somebody still has to reason about failure states, retries and ownership of state.
If an AI-built MVP has reached the point where auth, Edge Functions, payments and background jobs interact in ways that are hard to reason about, my MVP development service focuses on that production layer. You can also contact me for an audit before rebuilding the whole product.



