Files
supabase/apps/docs/content/troubleshooting/edge-function-shutdown-reasons-explained.mdx
3dffdefd6e fix(docs) Resolve 196 mdx lint warnings for just, quickly, actually, PostgreSQL (#47358)
Closes DOCS-1057
Contributes to DOCS-1052

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## Problem

We have hundreds of MDX lint warnings in our docs going against style
best practices.

## Solution

Remove and replace in context the following:

- PostgreSQL. There was only one. There was concern about exceptions,
but I found none.
- Just
- Quickly
- Actually

### What changed

Edits follow the [Google developer documentation style
guide](https://developers.google.com/style): concise, direct, active
voice. The flagged words were removed when the sentence still read well,
or replaced when meaning needed to be preserved.

### Common patterns

| Flagged word | Approach | Example |
|---|---|---|
| **just** (filler) | Removed | "you just installed" → "you installed" |
| **just** (limiting) | **only** | "just one row" → "only one row" |
| **just like** | **like** / **the same as** | "function just like
regular users" → "function like regular users" |
| **not just** | **not only** | "not just errors" → "not only errors" |
| **quickly** (performance) | **efficiently** or removed | "find rows
quickly" → "find rows efficiently" |
| **quickly** (time) | **soon** / **rapidly** / removed | "expires too
quickly" → "expires too soon" |
| **actually** (filler) | Removed | "actually execute" → "execute"; "is
actually the most common" → "is the most common" |

## Tophatting

1. See the diff.
2. See that content continues to make sense in context.
3. Locally, `cd apps/docs` and run `pnpm run lint:mdx`.
4. Search for "just," "actually," "quickly", and "PostgreSQL" and see
there are 0 warnings.




<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Updated wording across quickstarts, guides, and troubleshooting
articles for grammar, clarity, and consistent step-by-step phrasing.
* Clarified key concepts including Row Level Security policy evaluation
across Supabase products, deferred foreign key constraint behavior, and
when `EXPLAIN ANALYZE` executes queries (and related side effects).
* Refined several troubleshooting instructions and added guidance to cap
log payload size to reduce billed Logs Ingest volume.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nik Richers <nrichers@gmail.com>
Co-authored-by: Chris Chinchilla <chris.ward@supabase.io>
2026-06-29 09:40:25 -07:00

252 lines
10 KiB
Plaintext

---
title = "Edge Function shutdown reasons explained"
topics = [ "functions" ]
keywords = [ "shutdown", "termination", "event loop", "wall clock", "cpu time", "memory", "early drop" ]
database_id = "109b964f-c28c-4554-b059-cd8b165c63f8"
[[errors]]
http_status_code = 546
message = "Edge Function 'wall clock time limit reached'"
[[errors]]
message = "Edge Function terminated due to memory limit"
[[errors]]
message = "Edge Function terminated due to CPU limit"
---
Learn about the different reasons why an Edge Function (worker) might shut down and how to handle each scenario effectively.
## Understanding shutdown events
When an Edge Function stops executing, the runtime emits a `ShutdownEvent` with a specific `reason` that explains why the worker ended. Understanding these shutdown reasons helps you diagnose issues, optimize your functions, and build more resilient serverless applications.
These events are surfaced through logs and observability tools, allowing you to monitor function behavior and take appropriate action such as implementing retries, adjusting resource limits, or optimizing your code.
## Shutdown reasons
### EventLoopCompleted
**What it means:** The function's event loop finished naturally. There are no more pending tasks, timers, or microtasks. The worker completed all scheduled work successfully.
**When it happens:** This is the normal, graceful shutdown scenario. All synchronous code has executed, and all awaited promises have resolved.
**What to do:** Nothing special. This indicates successful completion. No retry is needed.
### WallClockTime
**What it means:** The worker exceeded the configured wall-clock timeout. This measures the total elapsed real time from when the function started, including time spent waiting for I/O, external API calls, and sleeps.
**When it happens:** Your function is taking too long to complete, regardless of how much actual computing it's doing. Currently, the wall clock limit is set at 400 seconds.
**What to do:**
- Break down long-running tasks into smaller functions
- Use streaming responses for operations that take time
- Consider moving long-running work to background jobs or queues
- Ensure your code handles partial completion gracefully
- Make operations idempotent so they can safely retry from the beginning
**Related:** See [Edge Function 'wall clock time limit reached'](./edge-function-wall-clock-time-limit-reached-Nk38bW) for more details.
### CPUTime
**What it means:** The worker consumed more CPU time than allowed. CPU time measures actual processing cycles used by your code, excluding time spent waiting for I/O or sleeping. Currently limited to 2000 milliseconds.
**When it happens:** Your function is performing too much computation. This includes complex calculations, data processing, encryption, or other CPU-intensive operations.
**What to do:**
- Profile your code to identify CPU-intensive sections
- Optimize algorithms for better performance
- Consider caching computed results
- Move heavy processing to background jobs or external services
- Break large datasets into smaller chunks
- Use more efficient data structures
### Memory
**What it means:** The worker's memory usage exceeded the allowed limit. The `ShutdownEvent` includes detailed memory data showing total memory, heap usage, and external allocations.
**When it happens:** Your function is consuming too much RAM. This commonly happens when buffering large files, loading entire datasets into memory, or creating many objects without cleanup.
**What to do:**
- Use streaming instead of buffering entire files or responses
- Process data in chunks rather than loading everything at once
- Be mindful of closures and variables that might prevent garbage collection
- Avoid accumulating large arrays or objects
- Review the `memory_used` fields in logs to identify whether heap or external memory is the issue
### EarlyDrop
**What it means:** The runtime detected that the function has completed all its work and can be shut down early, before reaching any resource limits. This is the most common shutdown reason and typically indicates efficient function execution.
**When it happens:** Your function has finished processing the request, sent the response, and has no remaining async work (pending promises, timers, or callbacks). The runtime recognizes that the worker can be safely terminated without waiting for timeouts or other limits.
**Why this is good:** `EarlyDrop` means your function is running efficiently. It completed without exhausting resources, and the runtime could reclaim the worker for other requests. Most well-designed functions should end with `EarlyDrop`.
**What to do:**
- Nothing: this is the desired outcome for most functions
- If you're seeing `EarlyDrop` but expected more work to happen, check for:
- Promises that weren't properly awaited
- Event listeners or timers that weren't cleaned up
- Background tasks that should have completed but didn't
- If you intentionally have background work that should continue after the response, make sure those promises are awaited before the function returns
### TerminationRequested
**What it means:** An external request explicitly asked the runtime to terminate the worker. This could be from orchestration systems, manual intervention, platform updates, deployments, or a user-initiated cancellation.
**When it happens:** The platform needs to stop your function immediately, often during deployments or infrastructure maintenance.
**What to do:**
- Implement graceful cleanup code, but expect it might not always run
- Design for abrupt termination. Use durable storage to persist work in progress
- Make operations atomic or use transactions where possible
- Track execution state externally so incomplete work can be detected and resumed
- Test your function's behavior when forcibly stopped
## Additional diagnostic events
While not shutdown reasons themselves, these events provide important context:
- **BootEvent / BootFailure:** Indicates whether a worker started successfully or failed during initialization
- **UncaughtException:** Signals an unhandled error with the exception message and CPU time used
- **LogEvent:** Runtime-emitted logs with severity levels (Debug, Info, Warning, Error)
- **WorkerMemoryUsed:** Detailed memory snapshot including total, heap, external memory, and memory checker data
## Shutdown event metadata
Each `ShutdownEvent` includes valuable diagnostic information:
- `reason`: One of the shutdown reasons described above
- `cpu_time_used`: Amount of CPU time consumed (in milliseconds)
- `memory_used`: Memory snapshot at shutdown with breakdown of total, heap, and external memory
- `execution_id`: Unique identifier for tracking this specific execution across logs and retries
## Best practices for resilient functions
### 1. Design for idempotency
Make your functions safe to run multiple times with the same input. Use execution IDs from metadata to detect duplicate runs and avoid repeating side effects.
```typescript
// Store execution_id to detect retries
const executionId = Deno.env.get('EXECUTION_ID')
const alreadyProcessed = await checkIfProcessed(executionId)
if (alreadyProcessed) {
return new Response('Already processed', { status: 200 })
}
```
### 2. Implement checkpointing.
Save progress frequently to durable storage
```typescript
// Save progress incrementally
for (const batch of dataBatches) {
await processBatch(batch)
await saveProgress(batchId)
}
```
### 3. Use streaming for large data
Avoid loading entire files or responses into memory. Stream data to reduce memory footprint.
```typescript
// Stream responses instead of buffering
return new Response(readableStream, {
headers: { 'Content-Type': 'application/json' },
})
```
### 4. Monitor and alert
Track shutdown reasons in your observability system. Set up alerts for:
- Frequent `Memory` shutdowns: investigate memory usage patterns
- Frequent `CPUTime` shutdowns: optimize computational work
- Frequent `WallClockTime` shutdowns: reduce latency or break up work
- Frequent `EarlyDrop` or `TerminationRequested`: check platform scaling and deployment patterns
Access your function logs at [Functions Logs](/dashboard/project/_/functions).
### 5. Handle cleanup gracefully
While you can't always rely on cleanup code running, implement it anyway for the cases where graceful shutdown is possible.
```typescript
// Cleanup handler (may not always run)
addEventListener('unload', () => {
// Close connections, flush buffers, etc.
cleanup()
})
```
## Example shutdown event payloads
**Normal completion:**
```json
{
"event": {
"Shutdown": {
"reason": "EventLoopCompleted",
"cpu_time_used": 12,
"memory_used": {
"total": 1048576,
"heap": 512000,
"external": 1000
}
}
},
"metadata": {
"execution_id": "4b6a4e2e-7c4d-4f8b-9e1a-2d3c4e5f6a7b"
}
}
```
**Wall-clock timeout:**
```json
{
"event": {
"Shutdown": {
"reason": "WallClockTime",
"cpu_time_used": 50,
"memory_used": {
"total": 2097152,
"heap": 1024000,
"external": 5000
}
}
},
"metadata": {
"execution_id": "5c7b5f3f-8d5e-5g9c-0f2b-3e4d5f6g7h8i"
}
}
```
## Troubleshooting checklist
Use this quick reference when investigating shutdown issues:
| Shutdown Reason | Primary Action |
| ---------------------------------------------- | --------------------------------------------------------------------------------------- |
| Many `Memory` shutdowns | Switch to streaming; process data in chunks; investigate heap vs external allocations |
| Many `CPUTime` shutdowns | Optimize algorithms; cache results; move heavy compute to background workers |
| Many `WallClockTime` shutdowns | Reduce I/O waits; use async operations; break into smaller functions |
| Frequent `EarlyDrop` or `TerminationRequested` | Check platform scaling policies; review deployment logs; implement better checkpointing |
## Additional resources
- [Debugging Edge Functions](/docs/guides/functions/logging)
- [Edge Function limits](/docs/guides/functions/limits)
- [Inspecting Edge Function environment variables](./inspecting-edge-function-environment-variables-wg5qOQ)