From cf063c4ae8674d6b18dd7894a17563e16e013cd2 Mon Sep 17 00:00:00 2001 From: Luiz Felipe Machado <56140722+luizfelmach@users.noreply.github.com> Date: Wed, 30 Sep 2026 22:07:29 -0300 Subject: [PATCH] docs: clarify self-hosted function timeout limits (#50807) --- .../guides/self-hosting/self-hosted-envoy.mdx | 48 ++++++++++--------- .../self-hosting/self-hosted-functions.mdx | 26 ++++++++-- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx b/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx index 60a0d76065c..810946f9ed3 100644 --- a/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx +++ b/apps/docs/content/guides/self-hosting/self-hosted-envoy.mdx @@ -104,29 +104,29 @@ sh run.sh restart api-gw Routes are matched in the order declared. The first matching prefix wins. Protected routes require a valid `apikey` header; open routes pass through without API key validation. -| Path prefix | Upstream | Path rewrite | Access control | Notes | -| ----------------------------------------- | --------- | ------------------------ | -------------- | ---------------------------------------------------------------------- | -| `/auth/v1/verify` | auth | `/verify` | Open | Email verification | -| `/auth/v1/callback` | auth | `/callback` | Open | OAuth callback | -| `/auth/v1/authorize` | auth | `/authorize` | Open | OAuth authorize | -| `/auth/v1/.well-known/jwks.json` | auth | `/.well-known/jwks.json` | Open | JWKS for third-party verification | -| `/.well-known/oauth-authorization-server` | auth | - | Open | OAuth 2.0 Authorization Server Metadata (RFC 8414) | -| `/auth/v1/sso/saml/acs` | auth | `/sso/saml/acs` | Open | SAML assertion consumer | -| `/auth/v1/sso/saml/metadata` | auth | `/sso/saml/metadata` | Open | SAML metadata | -| `/functions/v1/` | functions | `/` | `sb_` keys | Rejects invalid and conflicting `sb_` keys; others pass; timeout: 150s | -| `/storage/v1/` | storage | `/` | Bypass | Storage performs its own authorization | -| `/auth/v1/` | auth | `/` | API key | Protected Auth endpoints | -| `/rest/v1/` | rest | `/` | API key | PostgREST Open API root (requires secret key) | -| `/rest/v1/*` | rest | `/` | API key | PostgREST data endpoints | -| `/graphql/v1` | rest | `/rpc/graphql` | API key | pg_graphql (adds `Content-Profile: graphql_public`) | -| `/realtime/v1/api/tenants` | realtime | - | Denied | Realtime management API (blocked by default) | -| `/realtime/v1/api/openapi` | realtime | - | Denied | Realtime OpenAPI spec (blocked by default) | -| `/realtime/v1/api` | realtime | `/api` | API key | Realtime REST API (broadcast, channels, ping) | -| `/realtime/v1/` | realtime | `/socket/` | API key | Realtime WebSocket | -| `/pg/` | meta | `/` | API key | postgres-meta / Studio database operations (requires secret key) | -| `/api/mcp` | studio | - | Denied | MCP endpoint (blocked by default via RBAC DENY) | -| `/mcp` | studio | `/api/mcp` | Denied | MCP endpoint (blocked by default via RBAC DENY) | -| `/` (catch-all) | studio | - | Basic auth | Dashboard; strips inbound `Authorization` header | +| Path prefix | Upstream | Path rewrite | Access control | Notes | +| ----------------------------------------- | --------- | ------------------------ | -------------- | ---------------------------------------------------------------------------------------------------------- | +| `/auth/v1/verify` | auth | `/verify` | Open | Email verification | +| `/auth/v1/callback` | auth | `/callback` | Open | OAuth callback | +| `/auth/v1/authorize` | auth | `/authorize` | Open | OAuth authorize | +| `/auth/v1/.well-known/jwks.json` | auth | `/.well-known/jwks.json` | Open | JWKS for third-party verification | +| `/.well-known/oauth-authorization-server` | auth | - | Open | OAuth 2.0 Authorization Server Metadata (RFC 8414) | +| `/auth/v1/sso/saml/acs` | auth | `/sso/saml/acs` | Open | SAML assertion consumer | +| `/auth/v1/sso/saml/metadata` | auth | `/sso/saml/metadata` | Open | SAML metadata | +| `/functions/v1/` | functions | `/` | `sb_` keys | Rejects invalid and conflicting `sb_` keys; others pass; 160s idle timeout, 410s upstream response timeout | +| `/storage/v1/` | storage | `/` | Bypass | Storage performs its own authorization | +| `/auth/v1/` | auth | `/` | API key | Protected Auth endpoints | +| `/rest/v1/` | rest | `/` | API key | PostgREST Open API root (requires secret key) | +| `/rest/v1/*` | rest | `/` | API key | PostgREST data endpoints | +| `/graphql/v1` | rest | `/rpc/graphql` | API key | pg_graphql (adds `Content-Profile: graphql_public`) | +| `/realtime/v1/api/tenants` | realtime | - | Denied | Realtime management API (blocked by default) | +| `/realtime/v1/api/openapi` | realtime | - | Denied | Realtime OpenAPI spec (blocked by default) | +| `/realtime/v1/api` | realtime | `/api` | API key | Realtime REST API (broadcast, channels, ping) | +| `/realtime/v1/` | realtime | `/socket/` | API key | Realtime WebSocket | +| `/pg/` | meta | `/` | API key | postgres-meta / Studio database operations (requires secret key) | +| `/api/mcp` | studio | - | Denied | MCP endpoint (blocked by default via RBAC DENY) | +| `/mcp` | studio | `/api/mcp` | Denied | MCP endpoint (blocked by default via RBAC DENY) | +| `/` (catch-all) | studio | - | Basic auth | Dashboard; strips inbound `Authorization` header | @@ -134,6 +134,8 @@ MCP routes are denied at the gateway by default. Allowing local access requires +The `/functions/v1/` route sets `idle_timeout` to `160s` and `timeout` to `410s` in `volumes/api/envoy/lds.template.yaml`. These allow the runtime's 150-second request idle timeout and 400-second worker lifetime limit to expire first. See [Memory or timeout errors](/docs/guides/self-hosting/self-hosted-functions#memory-or-timeout-errors) for the runtime settings. + ## Authentication The gateway handles three authentication-related steps: dashboard basic auth on the catch-all route, API key enforcement on protected routes, and an opaque-to-internal key translation step that runs before enforcement. diff --git a/apps/docs/content/guides/self-hosting/self-hosted-functions.mdx b/apps/docs/content/guides/self-hosting/self-hosted-functions.mdx index 5ef0d0625b2..432ade2b385 100644 --- a/apps/docs/content/guides/self-hosting/self-hosted-functions.mdx +++ b/apps/docs/content/guides/self-hosting/self-hosted-functions.mdx @@ -210,11 +210,13 @@ For more details, see: ## Troubleshooting -### 400 "missing function name in request" +### 404 `NOT_FOUND` -The request URL must include the function name after `/functions/v1/`. For example, `/functions/v1/hello`. +The request URL must include the function name after `/functions/v1/`. For example, `/functions/v1/hello`. Check that the corresponding directory exists at `volumes/functions/hello/`. -### 500 error on invocation +### Function invocation errors + +Inspect the `sb-error-code` response header and see [Edge Functions error codes](/docs/guides/functions/error-codes) for details about the error. Check the functions service logs: @@ -222,7 +224,7 @@ Check the functions service logs: docker compose logs functions ``` -Common causes: syntax errors in your function code, invalid imports, or missing dependencies. +For 503 `BOOT_ERROR`, check for syntax errors, invalid imports, or missing dependencies that prevent the function from starting. ### 401 "invalid JWT" @@ -252,4 +254,18 @@ sh run.sh recreate functions ### Memory or timeout errors -The default limits are 150 MB memory and 60 seconds timeout per function invocation. These are set in `volumes/functions/main/index.ts`. To adjust them, edit the `memoryLimitMb` and `workerTimeoutMs` values and restart the functions service. +The default limits in `volumes/functions/main/index.ts` apply to each worker: + +| Setting | Default | Description | +| ------------------------ | ---------- | ------------------------------------------------------------------------------------------- | +| `memoryLimitMb` | 150 MB | Maximum memory usage. | +| `workerTimeoutMs` | 400,000 ms | Maximum worker lifetime. | +| `requestAbsentTimeoutMs` | 60,000 ms | Allows the worker to shut down after 60 seconds without requests when no tasks are pending. | + +To adjust these limits, edit the values in `volumes/functions/main/index.ts` and restart the functions service. + +Requests have a separate idle timeout of 150 seconds. This is set by `--user-worker-request-idle-timeout` in the functions service command in `docker-compose.yml`, with the value `150000` in milliseconds. Recreate the functions container after changing this value. + +The [Envoy gateway](/docs/guides/self-hosting/self-hosted-envoy#routes) has separate limits of 160 seconds of inactivity and a 410-second upstream response timeout. + +If you use the optional Kong gateway, `read_timeout` in `volumes/api/kong.yml` is set to `160000` milliseconds, allowing 160 seconds of inactivity between reads from the functions service.