fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(db): raise maintenance_work_mem in the migration runner - #511

Merged
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem
Aug 1, 2026
Merged

fix(db): raise maintenance_work_mem in the migration runner#511
AndresL230 merged 1 commit into
mainfrom
fix/migrate-maintenance-work-mem

Conversation

@AndresL230

Copy link
Copy Markdown
Collaborator

Applying the reconciled backlog (#510) to staging died seven files in:

ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB

0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase defaults maintenance_work_mem to 32 MB, so the build cannot complete — and because apply_migration wraps each file plus its ledger INSERT in one transaction and run() has no per-file recovery, it took the remaining four migrations down with it. The ledger stopped cleanly at 44 of 49 with no partial state, which is the one merciful thing about that failure mode.

This is not staging-specific. Any environment on the default hits it the first time 0039 runs — prod included, and prod has not been migrated yet.

Why per-session rather than per-environment

ALTER DATABASE ... SET only reaches backends started after it, and a pooled connection is frequently already established. Observed directly against Supavisor: a fresh backend picked up the new value while a reused one still reported 32 MB, which makes the change look like it silently did nothing. A session-level SET always lands on the connection actually running the DDL.

128 MB is transient per-operation memory during an index build, not a reservation, and leaves headroom over 0039's ~35 MB without being reckless on a small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.

The value is interpolated as a literal because SET does not accept a bound parameter. It is operator config, never request input, and a bad value fails loudly at the start rather than mid-migration.

Verification

Verified by using it — staging's remaining 5 migrations applied cleanly:

on disk 49 | recorded 49 | pending 0
PENDING none
ORPHANS none
DATA BLOCKERS none

That also closed#316 (avatars bucket now public=true) and #265 (assignments_source_check now admits 'gradescope').

1557 passed, 38 skipped; ruff check clean.

🤖 Generated with Claude Code

Applying the reconciled backlog to staging died seven files in:
ProgramLimitExceeded: memory required is 35 MB, maintenance_work_mem is 32 MB
0039_rag_vector_store builds an ivfflat index over VECTOR(768). Supabase
defaults maintenance_work_mem to 32 MB, so the build cannot complete — and
because apply_migration wraps each file plus its ledger INSERT in one
transaction and run() has no per-file recovery, it took the remaining four
migrations down with it. The ledger stopped at 44 of 49 with no partial state,
which is the one good thing about that failure mode.
This is not staging-specific. Any environment on the default hits it the first
time 0039 runs, prod included, and prod has not been migrated yet.
Set per session, not per environment. `ALTER DATABASE ... SET` only reaches
backends started after it, and a pooled connection is frequently already
established — observed directly against Supavisor, where a fresh backend picked
up the new value while a reused one still reported 32 MB, making the change look
like it had silently failed. A session-level SET always lands on the connection
actually running the DDL.
128 MB is transient per-operation memory during an index build, not a
reservation, and leaves headroom over 0039's ~35 MB without being reckless on a
small instance. MIGRATE_MAINTENANCE_WORK_MEM overrides it.
The SET is a literal rather than a bound parameter because SET does not accept
one; the value is operator config, never request input, and a bad value fails
loudly at the start instead of mid-migration.
Verified by using it: staging's remaining 5 migrations applied cleanly, and the
drift report now reports 49 on disk / 49 recorded / 0 pending / 0 orphans,
exit 0. That also closed#316 (avatars bucket now public=true) and #265
(assignments_source_check now admits 'gradescope').
1557 passed, 38 skipped; ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 1, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project ybgqdonkoqftwrmweuyv because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@AndresL230, you've reached your PR review limit, so we couldn't start this review.

Next review available in:12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 261e0a38-e95e-4b0e-9ffa-0ecb823d0b96

📥 Commits

Reviewing files that changed from the base of the PR and between fff26ce and 9218ad8.

📒 Files selected for processing (2)
  • backend/db/migrate.py
  • backend/tests/test_migrate_work_mem.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with Cloudflare Workers Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

StatusNameLatest CommitPreview URLUpdated (UTC)
✅ Deployment successful!
View logs
frontend-staging9218ad8Commit Preview URL

Branch Preview URL
Aug 01 2026, 07:08 AM

@AndresL230
AndresL230 merged commit 7534071 into mainAug 1, 2026
7 checks passed
@AndresL230
AndresL230 deleted the fix/migrate-maintenance-work-mem branch August 2, 2026 18:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

staging: avatars storage bucket is private but code expects public read

1 participant

@AndresL230