Supabase Edge Functions: The Limits Lovable Won't Mention
By Aakash Verma · · 4 min read
Supabase Edge Functions are small TypeScript programs that run on Supabase's Deno-based edge runtime, close to your users, whenever your app calls them. They're where a Supabase app keeps the code that can't run in the browser: Stripe webhooks, emails, calls to OpenAI with a secret key, anything that needs a password the user mustn't see. If you built your app with Lovable, you have them whether you know it or not, because Lovable writes your backend code as edge functions and deploys them for you.
That last part is why I'm writing this. When a tool writes the functions, nobody reads the limits page until something returns a 504. So here are the numbers, from Supabase's own Edge Functions limits page, checked October 19, 2026.
The four limits that actually bite
2 seconds of CPU time per request. Not wall time: CPU time. Waiting on a database query or an API call doesn't count, only the time your code spends computing. Parsing a big CSV, resizing images in JavaScript, or looping over 50,000 rows to build a report will hit it. Most webhook and email functions use a few milliseconds and never come close.
150 seconds of idle time. If the function hasn't sent a response 150 seconds after the request came in, the caller gets a 504 Gateway Timeout. This is the one AI features trip over: a function that waits for a long model answer before replying, or calls three APIs one after another, each slow on a bad day.
256 MB of memory. Fine for JSON. Not fine for loading a 100 MB PDF into memory to pull text out of it.
Wall clock: 150 seconds on the free plan, 400 on paid plans. That's how long a worker can stay alive, background work included. If you return a response early and keep working with EdgeRuntime.waitUntil(), the extra work still has to finish inside this window.

There are quieter limits too, and they explain a lot of strange bugs. Outgoing connections to ports 25 and 587 are blocked, so sending email over SMTP from a function won't work: use an email API like Resend or Postmark over HTTPS instead. Node libraries that need multithreading, like sharp and libvips, aren't supported, so the obvious way to make thumbnails isn't available. And a function only serves real HTML on a custom domain. Without one, a GET that returns text/html comes back as text/plain, which is very confusing the first time you see your page as raw source.
What they cost
Almost nothing, for most apps. Supabase's Edge Functions pricing gives the Free plan 500,000 invocations a month and Pro and Team 2 million, then charges $2 per million after that. An app with a thousand daily users calling a function ten times a day stays around 300,000 invocations a month.
The bill problems I'd look for are elsewhere: a function on a schedule that runs every minute for no reason, or a function that calls an AI model on every page load. The invocations are cheap. The model calls they make aren't.
The code AI tools get wrong
None of this is specific to Lovable. It's what any code generator does when it writes for a runtime it knows less well than Node.
CORS. A function called from the browser has to answer the OPTIONS preflight request and send the right Access-Control-Allow-* headers on every response, errors included. Generated code often adds the headers to the success response and forgets the error path, so the real error shows up in the browser console as a CORS failure, and you go hunting for the wrong bug.
Stripe webhooks. Stripe's signature check needs the raw request body, and in Deno you have to use the async version, stripe.webhooks.constructEventAsync, with Stripe's SubtleCrypto provider. The synchronous constructEvent from every Node tutorial fails here. Supabase has a Stripe webhook example that gets it right. If your payments "sometimes don't register", check this first. I covered the rest of that topic in Stripe webhooks: the parts that break in production.
Auth. By default a function checks that the caller sent a valid JWT. Webhooks from Stripe or GitHub don't send one, so someone turns verification off for that function, and the generated code may turn it off more broadly than it should. A function that changes data and accepts calls from anyone is worth ten minutes of your time to check.
Long work in a request. Anything that might take more than a few seconds (generating a report, processing an upload, a batch of emails) belongs in a queue, not in the request. On Supabase that can be pgmq with a scheduled function draining it. If you're on Node elsewhere, BullMQ is what I'd use.
When to move code off edge functions
Edge functions are good at short, stateless work: receive a webhook, check it, write a row, reply. I keep them for that. When a function starts needing more than a couple of seconds of CPU, a native image library, or a long-running connection, it's time for a small server or a worker, not a cleverer function. That's a normal step in an app's life, not a failure of the first version.
If your app was built with Lovable and the edge functions are where things have started breaking, that's exactly the work my agency Lovable 2 Live does. For anything else, book a free call. All consultation is free.
Introductory offer
Free cloud cost optimization. You only pay from what I save.
I cut your AWS, cloud, Supabase or Vercel bill for free and keep half of what I save for 6 months. Save nothing, pay nothing. Code, architecture and infrastructure.