All guidesSupabase RLS and keys
On this page

Cloudflare Workers and Supabase

SupabaseCloudflare

Too many subrequests by single Worker invocation.

By Ohad Krispin, founder of VibeRaven · LinkedIn

"Too many subrequests by single Worker invocation." means one request to your Cloudflare Worker made more outgoing requests than its limit allows, and every supabase-js call is one fetch to your Supabase project. Workers Free allows 50 subrequests per request and Workers Paid 10,000 by default, which you can raise up to 10 million with limits.subrequests in your Wrangler config. A loop that runs one query per item, such as one .select() per user, reaches 50 fast. Replace the loop with one query: .in() for a list of IDs, a foreign-table embed, or a Postgres function called with .rpc(). supabase-js does not throw here: it returns the message in error.message as "Error: Too many subrequests by single Worker invocation. To configure this limit, refer to https://developers.cloudflare.com/workers/wrangler/configuration/#limits". Checked against Cloudflare's limits docs on 2026-10-27.

Use this from your agent

  • Claude Code: 4 read-only tools; cannot see your repo.
    claude mcp add --transport http viberaven https://viberaven.dev/mcp
  • Codex: same server, in ~/.codex/config.toml.
    [mcp_servers.viberaven]
    url = "https://viberaven.dev/mcp"
  • In your repo: writes Vercel + Supabase check rules for your agent (what it writes).
    npx -y viberaven init

What counts as a subrequest

Cloudflare counts every fetch() a Worker makes and every call to Cloudflare services such as R2, KV and D1, and each hop of a redirect chain counts too. With supabase-js that means each .from() query, each .rpc(), each supabase.auth call such as getUser(), and each storage call. Workers Free also allows 1,000 subrequests to Cloudflare's internal services; Supabase is not one of them.

Replace the loop with one query

One query per item turns a page of 60 items into 60 subrequests. Ask for all of them at once:

// 1 subrequest per user: 60 users, 60 subrequests
for (const id of userIds) {
  const { data } = await supabase.from('profiles').select('*').eq('id', id).single()
}

// 1 subrequest in all
const { data, error } = await supabase.from('profiles').select('*').in('id', userIds)

// related rows in the same request, through a foreign key
const { data: posts } = await supabase.from('posts').select('id, title, profiles(username)')

Raise the limit on Workers Paid

Cloudflare's Wrangler docs list limits.subrequests: 50 is the most on a free account, and paid accounts default to 10,000 and can go up to 10,000,000. Raise it only after the loop is gone, since each subrequest still adds a round trip to Supabase.

// wrangler.jsonc
{
  "limits": {
    "subrequests": 20000
  }
}

Error: Too many subrequests.

Reports from 2024 and early 2025, including a Supabase discussion about the error appearing in production and not locally, show the shorter message "Error: Too many subrequests.". Reports from September and October 2026 show the longer message with the link to the limits configuration. Both mean the same limit.

Checklist

How to fix it, then check the fix

  1. 01Find the route that fails and count the Supabase calls one request makes, loops included.
  2. 02Replace per-item queries with .in(), an embedded select or one .rpc() call.
  3. 03Check error on every supabase-js result: this error comes back in error.message, not as a thrown exception.
  4. 04On Workers Paid, set limits.subrequests in your Wrangler config if the route really needs more.
  5. 05Deploy and call the route with the largest real input, then confirm in the Worker logs that it finished without the error.

Related

Sources

Official docs behind this checklist

FAQ

FAQ for builders before launch

Is the limit per Worker or per request?

Per invocation: Cloudflare's limits page counts subrequests for each request the Worker handles, so the count starts again with the next request.

Why did it work in development?

A Supabase discussion reports the error only in production. Test the route on a deployed Worker with production sized data before launch.