Skip to content

feat(relay-infra): the relay's own Cloud SQL instance and move-job identity (step 4, staging only) - #29564

Closed
Jinwoo-H wants to merge 3 commits into
mainfrom
step4-dedicated-db-terraform
Closed

Jinwoo-H wants to merge 3 commits into
mainfrom
step4-dedicated-db-terraform

Conversation

@Jinwoo-H

@Jinwoo-H Jinwoo-H commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Heads-up for staging Terraform: these resources already exist in staging state (rehearsal 10-16). Until this PR merges, a full staging plan from main fails on them (prevent_destroy); targeted applies are unaffected.

Files Added Deleted Net
Test 0 0 0 0
Prod 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​326 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​326

ELI5

The relay is getting its own database server, so heavy relay traffic can no longer slow down sign-in. This PR adds the Terraform for that server and for the identity of the one-off job that moves the data. It only turns them on in staging. Production stays off until Jinwoo gives the go.

What Changed

  • relay-dedicated-database.tf (new) adds the relay's own Cloud SQL instance:
    • Postgres 17, high availability, encrypted connections only, point-in-time recovery.
    • Enterprise Plus by design. Its default tier is db-perf-optimized-N-2.
    • max_connections is set explicitly to 500.
    • The maintenance window is Wednesday 09:00Z, so it never lands in the shared instance's Sunday window.
  • It also adds logins and secrets:
    • the relay login on the new instance;
    • a separate orca_relay_move login on each instance. This is the only change on the shared auth instance: one new user, no restart, no flag change.
    • three URL secrets.
  • It adds the move job's identity and grants:
    • a service account for the move job;
    • read access to the four secrets it needs;
    • cloudsql.client;
    • a small custom role that can only reset a Cloud SQL user's password;
    • write access to exactly one object in the control bucket, database-target.json.
  • Directors get read access to that one object. Cells can already read the bucket.
  • New variables: on/off, tier, edition, name, and zone. In staging.tfvars they are on, using Enterprise db-custom-2-7680 under the name ...-relay-db3 (reasons under Testing).
  • Users see no change. Nothing reads the new instance until the move tool (feat(relay): database move tool, part 1: change tracking, paced copy, sync and verify #29462/feat(relay): database move tool, part 2: fence, password restore and cutover #29463) writes the pointer. Relay processes on feat(relay): follow a database-target pointer with a hold-and-switch between two Postgres targets #29405 then follow it with a hold of about 1 s.

Why

  • Why a second instance. Relay and auth share one Cloud SQL instance today. Relay load (35 cells, ~1.8k row updates/s) can use up its connections and its memory cache, which slows sign-in.
  • Why not logical replication. The usual tool needs cloudsql.logical_decoding, and that flag restarts the shared instance, which is a sign-in outage. The move tool tracks changes with triggers instead, and this PR only provides what that tool needs.
  • Why Enterprise Plus. Its scale-up and maintenance outages are a few seconds, not ~1 minute.

Testing

All staging work used targeted applies and created resources only. I ran a full rehearsal on staging on 10-16, then put staging back to sleep the way I found it. Findings that shaped this PR:

  1. Enterprise Plus had no capacity anywhere in us-central1. Every create failed with "insufficient resources": N-2 in zones a, b, c and f, N-4, and C4 tiers. The same request succeeded in us-east1.
    • So staging uses Enterprise (relay_dedicated_database_edition). The move mechanism does not depend on the edition.
    • This is a production risk. Before G2, check Enterprise Plus capacity for production in us-central1. The fallback is Enterprise db-custom-4-15360.
  2. Deleted Cloud SQL instance names are reserved for about a week. That is why there is a name override and why staging uses -db3.
  3. Enterprise Plus needs retained backups above the log-retention days. Retention is now 14 backups against 7 days of logs.
  4. cloudsql.users.update returned 403 under an IAM resource.name condition. The move tool's rollback refused cleanly, before changing anything. The grant is now project-wide, on a role with three permissions.
  5. I measured Enterprise Plus scale-up on a probe instance in us-east1. Going N-2 to N-4 while a client ran 10 queries/s gave about 2 s of refused connections. It is not under 1 s.
  • terraform validate passes, and the targeted staging plan only adds resources.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below: infrastructure only, proven by the staging apply and rehearsal above.

Review

Stack: #29405 (relay switching), #29462 and #29463 (move tool). This Terraform PR is independent of them. Do not merge until Jinwoo's go. Until it merges, a full staging plan from main would show these staging resources as to-be-destroyed, and prevent_destroy would stop that plan. Targeted applies are not affected.

…, move logins and job identity (step 4)

Staging only (relay_dedicated_database_enabled); production needs its own go.
… on Enterprise after an Enterprise Plus stockout
…loud SQL refused it under a resource condition
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

Terraform adds an opt-in dedicated PostgreSQL 17 database for the relay, with configurable instance settings, database users, credentials, and Secret Manager URLs. It adds IAM grants for runtime identities and the move job, including scoped access to the relay control bucket. Staging enables the dedicated database with the ENTERPRISE edition and db-custom-2-7680 tier.

Priority: ⬇️ Low

Merge Risk: 🟡 Moderate · up to d4755

This change adds a dedicated relay database and move-job identity in staging only. The new move login on the shared auth database gets broader privileges than the move needs. It also has no explicit access grants to the existing relay tables, so the move could fail. Objects it creates might also be unreadable by the relay application after cutover. Resolve these database-permission gaps before relying on the move job.

Pre-merge checks: Passed 5
Check name Status Explanation
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly identifies the dedicated relay Cloud SQL instance and move-job identity, and it correctly limits the change to staging.
Description check Passed The description is detailed and covers the change, rationale, testing, risks, and review dependencies. It does not include an explicit issue link, a Visual Proof section with N/A, or the complete chec…
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (3 skipped: 3 unsupported.)

Full details: Description check

Explanation

The description is detailed and covers the change, rationale, testing, risks, and review dependencies. It does not include an explicit issue link, a Visual Proof section with N/A, or the complete checklist, but these omissions do not prevent the description from being mostly complete.

✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 66394219-5b01-4a80-8e7c-59b603865dd9
📥 Commits

Reviewing files that changed from the base of the PR and between 127704b and d4755e2.

📒 Files selected for processing: 3
  • cloud/infra/terraform/environments/staging.tfvars
  • cloud/infra/terraform/relay-dedicated-database.tf
  • cloud/infra/terraform/variables.tf

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

count = local.relay_dedicated_database_count

project = var.project_id
name = "orca_relay_move"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Give the shared-instance move login a scoped database role.

Cloud SQL automatically grants this built-in login cloudsqlsuperuser. That role permits broad operations, including creating roles and databases, on the shared auth instance. The move job needs access to relay data, not those instance-wide privileges. Create a scoped PostgreSQL role and assign it to orca_relay_move; grant the move operations explicitly. (docs.cloud.google.com)


🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Inspect the move tool and repository-owned SQL for grants and ownership changes.
fd -i 'database-move-cli\.ts' -x rg -n -C 4 -i \
  'relay-move|GRANT|SET ROLE|ALTER (TABLE|SCHEMA|DEFAULT PRIVILEGES)|CREATE (TABLE|SCHEMA)'
rg -n -C 3 -i 'orca_relay_move|GRANT .*orca_relay|ALTER DEFAULT PRIVILEGES' cloud

Repository: stablyai/orca

Length of output: 2069


🏁 Script executed:

set -euo pipefail
printf '%s\n' '--- move tool candidates ---'
rg --files -g '*database*move*' -g '*move*database*' -g '*.ts' -g '*.sql' | sort
printf '%s\n' '--- move workflow references ---'
rg -n -i -F -- 'database-move-cli' . || test "$?" -eq 1
rg -n -i -e 'relay[-_ ]move' -e 'orca_relay_move' -e 'SET ROLE' -e 'GRANT ' -e 'ALTER DEFAULT PRIVILEGES' -e 'CREATE TABLE' -e 'CREATE SCHEMA' --glob '!node_modules/**' --glob '!vendor/**' --glob '!dist/**' --glob '!build/**' . || test "$?" -eq 1

Repository: stablyai/orca

Length of output: 45660


🏁 Script executed:

set -euo pipefail
log=/tmp/coderabbit-shell-logs/shell-output-ujdmPa
printf '%s\n' '--- exact move-tool matches in prior output ---'
rg -n -i -e 'database-move-cli' -e 'orca_relay_move' -e 'relay-move' -e 'ALTER DEFAULT PRIVILEGES' -e 'SET ROLE' "$log" | head -n 200 || test "$?" -eq 1
printf '%s\n' '--- candidate path lines from prior output ---'
rg -n -i -e 'database.*move' -e 'move.*database' "$log" | head -n 200 || test "$?" -eq 1

Repository: stablyai/orca

Length of output: 40991


🏁 Script executed:

set -euo pipefail
printf '%s\n' '--- orca_relay references ---'
rg -n -F -- 'orca_relay' cloud/infra cloud/apps/relay cloud/packages 2>/dev/null || test "$?" -eq 1
printf '%s\n' '--- relay schema ownership and privilege statements ---'
rg -n -i -e 'CREATE SCHEMA' -e 'ALTER .*OWNER' -e 'GRANT ' -e 'REVOKE ' -e 'DEFAULT PRIVILEGES' -e 'role' cloud/apps/relay cloud/packages/postgres-schema cloud/infra 2>/dev/null || test "$?" -eq 1
printf '%s\n' '--- database move candidate files ---'
rg --files cloud | rg -i 'database.*move|move.*database|relay.*move|move.*relay' || true

Repository: stablyai/orca

Length of output: 41039


🏁 Script executed:

set -euo pipefail
printf '%s\n' '--- shared database Terraform ---'
nl -ba cloud/infra/terraform/relay-database.tf | sed -n '1,180p'
printf '%s\n' '--- dedicated database Terraform ---'
nl -ba cloud/infra/terraform/relay-dedicated-database.tf | sed -n '70,145p'
printf '%s\n' '--- schema package entrypoints ---'
nl -ba cloud/packages/postgres-schema/src/apply-postgres-schema.ts | sed -n '1,260p'
printf '%s\n' '--- schema application call sites ---'
rg -n -F -e 'applyPostgresSchema' -e 'apply-postgres-schema' -e 'POSTGRES_URL' -e 'DATABASE_URL' cloud/apps/relay cloud/packages/postgres-schema cloud/infra/terraform | head -n 200 || test "$?" -eq 1

Repository: stablyai/orca

Length of output: 32651


🏁 Script executed:

set -euo pipefail
printf '%s\n' '--- relay database startup and schema call ---'
nl -ba cloud/apps/relay/src/database.ts | sed -n '1440,1525p'
printf '%s\n' '--- relay runtime database URL bindings ---'
nl -ba cloud/infra/terraform/relay.tf | sed -n '190,235p'
nl -ba cloud/infra/terraform/relay.tf | sed -n '520,565p'
printf '%s\n' '--- relay schema DDL sources ---'
rg -n -i -e 'CREATE TABLE' -e 'CREATE SEQUENCE' -e 'CREATE SCHEMA' -e 'ALTER TABLE' -e 'CREATE INDEX' cloud/apps/relay/src/database.ts cloud/apps/relay/src --glob '*.ts' | head -n 160 || test "$?" -eq 1

Repository: stablyai/orca

Length of output: 24575


Grant orca_relay_move access to relay objects before using it.

The relay application connects as orca_relay, and schema startup applies PostgreSQL DDL through that connection. Terraform creates a separate orca_relay_move user but defines no table, sequence, schema, or default-privilege grants. cloudsqlsuperuser is not PostgreSQL SUPERUSER, so it does not bypass object ownership. The move can therefore fail when it reads or updates existing relay tables. Objects created by the move login on the dedicated instance may also be inaccessible to orca_relay after cutover.

Add the required grants or transfer ownership. Ensure the move workflow preserves application access to objects created during the move.

@OrcaWin

OrcaWin commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Closing because #31792 (307f0cdaeedc25ce0b3bae1cd96d66df914fa458) moved production/staging Terraform, deployment contracts and operator tools into private stablyai/orca-cloud; current cloud/README.md documents that ownership.

This PR creates the dedicated relay database, move-job identity/IAM and secrets, with staging-only enablement. Its Terraform root, variables and staging tfvars now belong to that private repository. The public PR cannot reconcile the active staging state or grant the move job its required database roles. I also read the permission/ownership findings in review; closure does not resolve those findings or assert that staging state is safe to apply.

I reviewed the complete patch and discussion. The private repository is inaccessible to this audit, so any still-needed work must be carried forward there; this is a repository-ownership closure, not a claim that the operational issue is fixed.

@OrcaWin OrcaWin closed this Oct 26, 2026
Sign up for free to 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.

2 participants