fix(db): reclaim Capgo-EU swap pressure without upgrading#2721
Conversation
Batched queue/audit cleanups, hourly http_response truncate, slim audit payloads, and allow nulling migrated dual-storage manifest arrays that were blocked by bundle_already_ready. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds database cleanup functions, scheduled maintenance, manual reclaim and verification scripts, reduced audit/HTTP payloads, encrypted-bundle update enforcement, related tests, and builtin version field initialization. ChangesSupabase swap memory controls
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant reclaim_supabase_swap.sql
participant cleanup_net_http_response
participant cleanup_queue_messages
participant null_migrated_app_version_manifests
participant cleanup_old_audit_logs
participant DatabaseTables
reclaim_supabase_swap.sql->>cleanup_net_http_response: truncate HTTP response rows
reclaim_supabase_swap.sql->>cleanup_queue_messages: delete archived and stuck queue rows
cleanup_queue_messages->>DatabaseTables: process PGMQ tables in batches
reclaim_supabase_swap.sql->>null_migrated_app_version_manifests: null fully migrated manifests
null_migrated_app_version_manifests->>DatabaseTables: update app_versions
reclaim_supabase_swap.sql->>cleanup_old_audit_logs: delete audit rows older than 30 days
cleanup_old_audit_logs->>DatabaseTables: process audit_logs in batches
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
Merging this PR will degrade performance by 40.43%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | /updates manifest response with metadata |
88.3 µs | 148.3 µs | -40.43% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing fix/supabase-swap-memory (4757e8a) with main (255357c)2
Footnotes
-
2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
-
No successful run was found on
main(e4496db) during the generation of this report, so 255357c was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩
Co-authored-by: Cursor <cursoragent@cursor.com>
Also fill created_by_apikey_rbac_id on builtin version stubs so frontend typecheck stays green. Co-authored-by: Cursor <cursoragent@cursor.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_f92bdb90-dcd3-4791-acbf-235375a3d673) |
There was a problem hiding this comment.
Stale comment
Risk: high. Cursor Bugbot did not complete (check skipped; usage limit reached), so there is no clean automated review signal. This PR adds a large production database migration and cron changes for Capgo-EU swap reclamation, which exceeds the low-risk approval threshold and needs human review before merge.
Sent by Cursor Approval Agent: Pull Request Approver External
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/migrations/20260722082019_fix_supabase_swap_memory.sql`:
- Around line 586-601: Update the encryption enforcement block around
bundle_is_encrypted and bundle_key_id so UPDATE operations with unchanged
session_key and key_id bypass the checks, allowing manifest-nulling cleanup on
legacy rows. Preserve the existing encryption validation for inserts and updates
that change either credential, using the OLD versus NEW values to detect
unchanged fields.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d50026b6-f2fc-424f-8fc0-fa1c4b816a5a
📒 Files selected for processing (7)
scripts/ops/reclaim_supabase_swap.sqlscripts/ops/verify_supabase_swap.sqlsrc/services/versions.tssupabase/migrations/20260722082019_fix_supabase_swap_memory.sqlsupabase/tests/55_test_audit_log_cleanup_cron.sqltests/audit-logs.test.tstests/cleanup_swap_memory.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
There was a problem hiding this comment.
All reported issues were addressed across 7 files
Confidence score: 5/5
- Safe to merge after the addressed issues were fixed.
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
Legacy unencrypted bundles in encryption-enforced orgs must still be reclaimable by null_migrated_app_version_manifests. Co-authored-by: Cursor <cursoragent@cursor.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_7b864b82-ed80-4602-b128-56e1288190d3) |
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped; usage limit reached), and this production database migration with data-deletion cron changes exceeds the medium-risk approval threshold. Human review is required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped; usage limit reached) and this production database migration with data-deletion cron changes exceeds the low-risk approval threshold. Human review is required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver External
|
Addressed the review note: |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql (2)
53-63: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winDo not delete messages still leased by a consumer.
read_ct > 5can match a message whosevtis still in the future, so the hourly job can delete an in-flight retry. PGMQ incrementsread_cton reads and usesvtas the consumer visibility lease. (pgmq.github.io)Proposed fix
- WHERE read_ct > 5 + WHERE read_ct > 5 + AND vt <= pg_catalog.now()Also add coverage proving a
read_ct > 5message with a futurevtremains queued.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@supabase/migrations/20260722082019_fix_supabase_swap_memory.sql` around lines 53 - 63, Update the dynamic DELETE query in the queue cleanup job to exclude messages whose visibility timeout `vt` is still in the future, while retaining the existing `read_ct > 5` and batch-size criteria. Add coverage demonstrating that a message with `read_ct > 5` and future `vt` remains queued.
28-63: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winFully qualify catalog functions in SECURITY DEFINER code.
format,lower,to_jsonb, andjsonb_build_objectare unqualified despite the empty search path. Prefix them withpg_catalog.consistently.
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql#L28-L63: usepg_catalog.format(...)for both dynamic cleanup statements.supabase/migrations/20260722082019_fix_supabase_swap_memory.sql#L381-L410: usepg_catalog.lower(...),pg_catalog.to_jsonb(...), andpg_catalog.jsonb_build_object(...).As per coding guidelines, “Every PostgreSQL function must use
SET search_path = ''and fully qualified schema and object names.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@supabase/migrations/20260722082019_fix_supabase_swap_memory.sql` around lines 28 - 63, Fully qualify catalog function calls in the SECURITY DEFINER migration: update both dynamic cleanup statements at supabase/migrations/20260722082019_fix_supabase_swap_memory.sql lines 28-63 to use pg_catalog.format, and update the serialization logic at lines 381-410 to use pg_catalog.lower, pg_catalog.to_jsonb, and pg_catalog.jsonb_build_object.Source: Coding guidelines
tests/cleanup_swap_memory.test.ts (1)
27-27: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy liftIsolate these destructive database tests per worker.
These calls delete/truncate shared queue,
net, andapp_versionsstate; the encryption test also flips a shared seed org’s policy. Parallel test workers can lose fixtures or reset each other’s encryption state.
tests/cleanup_swap_memory.test.ts#L27-L27: run queue cleanup in a worker-isolated database.tests/cleanup_swap_memory.test.ts#L54-L54: isolate the globalnet._http_responsetruncation.tests/cleanup_swap_memory.test.ts#L98-L98: isolate global manifest cleanup.tests/cleanup_swap_memory.test.ts#L168-L225: create and mutate a dedicated org rather than the first seeded org.As per coding guidelines, “Design all tests for parallel execution” and “avoid modifying shared seed resources.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/cleanup_swap_memory.test.ts` at line 27, Isolate all destructive database operations in tests/cleanup_swap_memory.test.ts per worker: update the queue cleanup at lines 27-27, net._http_response truncation at 54-54, and manifest cleanup at 98-98 to use the worker-isolated database. In the encryption test at lines 168-225, create and mutate a dedicated organization instead of the shared first seeded organization, preserving the existing assertions and behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@supabase/migrations/20260722082019_fix_supabase_swap_memory.sql`:
- Around line 53-63: Update the dynamic DELETE query in the queue cleanup job to
exclude messages whose visibility timeout `vt` is still in the future, while
retaining the existing `read_ct > 5` and batch-size criteria. Add coverage
demonstrating that a message with `read_ct > 5` and future `vt` remains queued.
- Around line 28-63: Fully qualify catalog function calls in the SECURITY
DEFINER migration: update both dynamic cleanup statements at
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql lines 28-63 to
use pg_catalog.format, and update the serialization logic at lines 381-410 to
use pg_catalog.lower, pg_catalog.to_jsonb, and pg_catalog.jsonb_build_object.
In `@tests/cleanup_swap_memory.test.ts`:
- Line 27: Isolate all destructive database operations in
tests/cleanup_swap_memory.test.ts per worker: update the queue cleanup at lines
27-27, net._http_response truncation at 54-54, and manifest cleanup at 98-98 to
use the worker-isolated database. In the encryption test at lines 168-225,
create and mutate a dedicated organization instead of the shared first seeded
organization, preserving the existing assertions and behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 8c771c73-a86d-4551-9655-cafe970bfbc6
📒 Files selected for processing (2)
supabase/migrations/20260722082019_fix_supabase_swap_memory.sqltests/cleanup_swap_memory.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
Bound cron cleanup work per invocation, require full manifest migration before nulling arrays, and keep native_packages locked on ready bundles. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped; usage limit reached) and this production database migration with scheduled data-deletion changes exceeds the low-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver External
Restore the partial app_versions index before hourly nulling runs, and exit the queue loop immediately when the global batch budget is spent. Co-authored-by: Cursor <cursoragent@cursor.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_dbd58ca7-7acb-460b-9a3e-2d7161a62bc2) |
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped due to usage limits) and this production database migration with scheduled data-deletion changes exceeds the medium-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped due to usage limits), and this production database migration with scheduled data-deletion changes exceeds the low-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver External
There was a problem hiding this comment.
All reported issues were addressed
Confidence score: 5/5
- Safe to merge after the addressed issues were fixed.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
file_name may be normalized during table migration, so entry equality must not require the legacy array's original file_name string. Co-authored-by: Cursor <cursoragent@cursor.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b743ad86-b685-4cd1-9241-ab869e642e96) |
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped due to usage limits) and this production database migration with scheduled data-deletion changes exceeds the low-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver External
There was a problem hiding this comment.
Stale comment
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped; usage limit reached), and this production database migration with scheduled data-deletion changes exceeds the medium-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver
There was a problem hiding this comment.
2 issues found and verified against the latest diff
Confidence score: 2/5
- In
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql, a plainCREATE INDEXcan take a write-blocking lock onapp_versions, potentially blocking all bundle creates/updates for the duration of the build—switch to a non-blocking index build (or otherwise bound the lock/transaction) before merging. - In
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql, empty non-NULL manifests are never reclaimed and remain inapp_versions_manifest_present_idx, so the hourly job may repeatedly scan them and add unnecessary load—remove the cardinality filter so vacuous entries can be cleaned up.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="supabase/migrations/20260722082019_fix_supabase_swap_memory.sql">
<violation number="1" location="supabase/migrations/20260722082019_fix_supabase_swap_memory.sql:180">
P3: Empty non-NULL manifests are never reclaimed, and they remain in `app_versions_manifest_present_idx`, so each hourly run may repeatedly scan them. Removing this cardinality filter safely lets the vacuous “every entry migrated” check normalize empty arrays to NULL.</violation>
<violation number="2" location="supabase/migrations/20260722082019_fix_supabase_swap_memory.sql:569">
P2: Applying this migration can block all bundle creates and updates for the full index build, because regular `CREATE INDEX` takes a write-blocking lock on `app_versions`; the duration is not bounded by the cleanup batch limits. Consider building this index concurrently through the maintenance ops path, or include migration application itself in the maintenance window.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 9 files
Confidence score: 5/5
- Safe to merge after the addressed issues were fixed.
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
Drop write-blocking index creation from the migration (ops uses CREATE INDEX CONCURRENTLY) and stop requiring normalized file_name matches in check_encrypted_bundle_on_insert. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d0e8ae0a-bce7-4a82-9ecc-12bf17ca17b2) |
There was a problem hiding this comment.
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped due to usage limits) and this production database migration with scheduled data-deletion changes exceeds the low-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver External
There was a problem hiding this comment.
Risk: high. Not approving because Cursor Bugbot did not complete (check skipped due to usage limits) and this production database migration with scheduled data-deletion changes exceeds the medium-risk approval threshold. Human review is still required; Dalanir and WcaleNieWolny are already assigned as reviewers.
Sent by Cursor Approval Agent: Pull Request Approver
There was a problem hiding this comment.
4 issues found across 7 files
Confidence score: 2/5
- In
scripts/ops/reclaim_supabase_swap.sqlandscripts/ops/verify_supabase_swap.sql, an interrupted concurrent index build can leave an INVALID index that still satisfiesIF NOT EXISTS, so reruns and verification may both pass while hourly cleanup runs without the intended pagination index; this risks ongoing slow/inefficient manifest cleanup after deploy — update verification to checkpg_index.indisvalidand ensure invalid indexes are dropped/rebuilt before merging. - In
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql,TRUNCATEcan block onACCESS EXCLUSIVEwith nolock_timeoutwhileprocess_all_cron_tasks()holds the global cron lock, which could stall scheduled jobs indefinitely if contention occurs — add a short lock timeout/fallback path before merging. - In
supabase/migrations/20260722082019_fix_supabase_swap_memory.sql, the reclaim logic repeats the same migration anti-join up to three times per row and includes an unreachable copy inside the ready-bundle lock, increasing query cost and maintenance risk in a hot path — compute eligibility once and reuse it to de-risk runtime overhead.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/ops/reclaim_supabase_swap.sql">
<violation number="1" location="scripts/ops/reclaim_supabase_swap.sql:37">
P2: A lock timeout or interrupted concurrent build leaves an invalid index that every instructed rerun skips because of `IF NOT EXISTS`, so manifest cleanup can proceed with the intended pagination index unusable. Detect and drop an invalid same-name index before retrying the concurrent build.</violation>
</file>
<file name="scripts/ops/verify_supabase_swap.sql">
<violation number="1" location="scripts/ops/verify_supabase_swap.sql:73">
P2: An interrupted concurrent build can appear here by name while remaining INVALID, leaving hourly manifest cleanup without the intended index and preventing `IF NOT EXISTS` from rebuilding it. Exposing `pg_index.indisvalid`/`indisready` and the definition would let operators identify and repair that state.
(Based on your team's feedback about building the manifest index concurrently.) [FEEDBACK_USED]</violation>
</file>
<file name="supabase/migrations/20260722082019_fix_supabase_swap_memory.sql">
<violation number="1" location="supabase/migrations/20260722082019_fix_supabase_swap_memory.sql:109">
P2: Hourly cleanup can stall every scheduled task indefinitely because `TRUNCATE` waits for `ACCESS EXCLUSIVE` and this function has no `lock_timeout` while `process_all_cron_tasks()` holds the global cron lock. A short function-level `lock_timeout` would let the processor catch lock contention and continue.</violation>
<violation number="2" location="supabase/migrations/20260722082019_fix_supabase_swap_memory.sql:620">
P2: Manifest reclaim performs the same migration anti-join up to three times per row, and the copy in the ready-bundle lock is unreachable because the first copy already raises. Computing the eligibility once and reusing it would materially reduce reclaim-trigger work.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| -- --------------------------------------------------------------------------- | ||
| -- 0b) Candidate index for hourly nulling (non-blocking; must be outside a tx) | ||
| -- --------------------------------------------------------------------------- | ||
| CREATE INDEX CONCURRENTLY IF NOT EXISTS app_versions_manifest_present_idx |
There was a problem hiding this comment.
P2: A lock timeout or interrupted concurrent build leaves an invalid index that every instructed rerun skips because of IF NOT EXISTS, so manifest cleanup can proceed with the intended pagination index unusable. Detect and drop an invalid same-name index before retrying the concurrent build.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/reclaim_supabase_swap.sql, line 37:
<comment>A lock timeout or interrupted concurrent build leaves an invalid index that every instructed rerun skips because of `IF NOT EXISTS`, so manifest cleanup can proceed with the intended pagination index unusable. Detect and drop an invalid same-name index before retrying the concurrent build.</comment>
<file context>
@@ -0,0 +1,102 @@
+-- ---------------------------------------------------------------------------
+-- 0b) Candidate index for hourly nulling (non-blocking; must be outside a tx)
+-- ---------------------------------------------------------------------------
+CREATE INDEX CONCURRENTLY IF NOT EXISTS app_versions_manifest_present_idx
+ ON public.app_versions USING btree (id)
+ WHERE manifest IS NOT NULL;
</file context>
| ) | ||
| ORDER BY name; | ||
|
|
||
| SELECT indexname |
There was a problem hiding this comment.
P2: An interrupted concurrent build can appear here by name while remaining INVALID, leaving hourly manifest cleanup without the intended index and preventing IF NOT EXISTS from rebuilding it. Exposing pg_index.indisvalid/indisready and the definition would let operators identify and repair that state.
(Based on your team's feedback about building the manifest index concurrently.)
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/ops/verify_supabase_swap.sql, line 73:
<comment>An interrupted concurrent build can appear here by name while remaining INVALID, leaving hourly manifest cleanup without the intended index and preventing `IF NOT EXISTS` from rebuilding it. Exposing `pg_index.indisvalid`/`indisready` and the definition would let operators identify and repair that state.
(Based on your team's feedback about building the manifest index concurrently.) </comment>
<file context>
@@ -0,0 +1,121 @@
+)
+ORDER BY name;
+
+SELECT indexname
+FROM pg_indexes
+WHERE schemaname = 'public'
</file context>
| OR NEW.external_url IS DISTINCT FROM OLD.external_url | ||
| OR NEW.checksum IS DISTINCT FROM OLD.checksum | ||
| OR (NEW.manifest IS DISTINCT FROM OLD.manifest AND NEW.manifest IS NOT NULL) | ||
| -- Nulling is allowed only when public.manifest has every expected entry. |
There was a problem hiding this comment.
P2: Manifest reclaim performs the same migration anti-join up to three times per row, and the copy in the ready-bundle lock is unreachable because the first copy already raises. Computing the eligibility once and reusing it would materially reduce reclaim-trigger work.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At supabase/migrations/20260722082019_fix_supabase_swap_memory.sql, line 620:
<comment>Manifest reclaim performs the same migration anti-join up to three times per row, and the copy in the ready-bundle lock is unreachable because the first copy already raises. Computing the eligibility once and reusing it would materially reduce reclaim-trigger work.</comment>
<file context>
@@ -0,0 +1,778 @@
+ OR NEW.external_url IS DISTINCT FROM OLD.external_url
+ OR NEW.checksum IS DISTINCT FROM OLD.checksum
+ OR (NEW.manifest IS DISTINCT FROM OLD.manifest AND NEW.manifest IS NOT NULL)
+ -- Nulling is allowed only when public.manifest has every expected entry.
+ OR (
+ NEW.manifest IS NULL
</file context>
| BEGIN | ||
| -- Responses are only used for short-lived async HTTP debugging. | ||
| -- Truncate reclaims disk; row deletes do not. | ||
| TRUNCATE TABLE net._http_response; |
There was a problem hiding this comment.
P2: Hourly cleanup can stall every scheduled task indefinitely because TRUNCATE waits for ACCESS EXCLUSIVE and this function has no lock_timeout while process_all_cron_tasks() holds the global cron lock. A short function-level lock_timeout would let the processor catch lock contention and continue.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At supabase/migrations/20260722082019_fix_supabase_swap_memory.sql, line 109:
<comment>Hourly cleanup can stall every scheduled task indefinitely because `TRUNCATE` waits for `ACCESS EXCLUSIVE` and this function has no `lock_timeout` while `process_all_cron_tasks()` holds the global cron lock. A short function-level `lock_timeout` would let the processor catch lock contention and continue.</comment>
<file context>
@@ -0,0 +1,778 @@
+BEGIN
+ -- Responses are only used for short-lived async HTTP debugging.
+ -- Truncate reclaims disk; row deletes do not.
+ TRUNCATE TABLE net._http_response;
+ RAISE NOTICE 'cleanup_net_http_response: truncated net._http_response';
+END;
</file context>





Summary (AI generated)
cleanup_queue_messages(2-day retention, hourly), hourlynet._http_responsetruncate, batched 30-day audit cleanup, slimapp_versionsaudit payloads, and hourly nulling of leftover dual-storagemanifestarrays.manifest/native_packagesafter upload incheck_encrypted_bundle_on_insertso reclaim is no longer blocked bybundle_already_ready.Motivation (AI generated)
Capgo-EU was swap-thrashing and restarting. Primary traffic is small (
devices/statsnearly empty); pressure came from unreclaimed bloat (~5GB emptynet._http_response, multi-GB stalepgmqarchives, fat audit TOAST, and dual-storageapp_versions.manifestarrays that could not be cleared).Business Impact (AI generated)
Keeps the current DB size workable, reduces OOM/restart risk for console and internal jobs, and avoids an unnecessary primary compute upgrade.
Test Plan (AI generated)
bun run supabase:db:resetapplies20260722082019_fix_supabase_swap_memory.sqlbun run supabase:with-env -- bunx vitest run tests/cleanup_swap_memory.test.ts tests/enforce-encrypted-bundles.test.ts(26 passed)scripts/ops/reclaim_supabase_swap.sqlin a maintenance windowscripts/ops/verify_supabase_swap.sql(sizes down, archives <2d, cron tasks present, fewerserver restartedrows)Generated with AI
Made with Cursor
Summary by CodeRabbit