Runbook: Neon Azure to AWS Migration
Runbook: Move the production database from Neon Azure East US 2 to Neon AWS us-east-1
Status: Executed 2026-10-11. The AWS database is live behind Hyperdrive; the Azure project is retained as the rollback target. Inventory taken 2026-10-11 against the production branch.
Executor: a human operator using the Neon Console, a terminal with Postgres 17 client tools, and the Cloudflare dashboard. No GitHub steps are required.
Why
Neon deprecated its Azure regions on 2026-04-07. As of 2026-10-05 azure-eastus2 (where this project lives) no longer receives feature updates, and Neon has said it will announce a final end-of-service date without giving one. A project’s region is fixed at creation, so the move means a new project in aws-us-east-1 (Neon’s mapping for azure-eastus2), a data copy, and a cutover. See Neon’s Azure regions deprecation notice and Migrate to another Neon region.
Both regions are in the Virginia metro, so latency from Cloudflare should be effectively unchanged.
What is being migrated
Source project: bloqr-db (twilight-river-73901472), org Bloqr Systems, Postgres 17.11.
| Item | Value |
|---|---|
| Live database | adblock-compiler (the name is checked by worker/handlers/health.ts; keep it identical) |
| Size | About 10 MB for the database; 41.6 MB project logical size |
| Schema | Single public schema; all tables owned by neondb_owner; 1 sequence; 0 large objects |
| Extensions | plpgsql only |
| Applied migrations | 9 (of 14 in prisma/migrations/, see “Pending migrations” below) |
| Hyperdrive | hyperdrive-adblockdb-neon-prod (800f7e2edc86488ab24e8621982e9ad7), origin ep-winter-term-a8rxh2a9-pooler.eastus2.azure.neon.tech:5432, user neondb_owner, query caching enabled |
| Logical replication | Enabled on the project but unused: no publications or subscriptions, only Neon’s internal wal_proposer_slot / wal_retention_slot |
Row counts on production (exact COUNT(*), 2026-10-11). Live tables (sessions, deployment_counter) will drift, so take a fresh count immediately before dumping.
| Table | Rows |
|---|---|
deployment_history | 312 |
sessions | 41 |
api_keys | 19 |
deployment_counter | 17 |
account | 10 |
users | 10 |
_prisma_migrations | 9 |
waitlist | 7 |
subscription_plans | 4 |
member | 2 |
organization | 1 |
| 23 other tables | 0 |
Decisions already made
- Early beta, no write freeze. Writes that land on the old database during the switch may be lost. Accepted.
- Only the
productionbranch matters.staginganddev/jaysonare test branches and are rebuilt, not migrated. - Logical replication is not carried over and is not needed. Do not enable it on the new project.
- The Neon Data API and the
neondbdatabase are not carried over. Nothing in the repo uses them, andneondbcontains no tables. - Roles
authenticator,anonymous,authenticated,adblockdb_owner,jayson-knightare not carried over. They own nothing and hold no grants inadblock-compiler(verified onstaging; re-verify onproductionwith the check in step 0). Onlyneondb_owneris used by the app. - The read replica
ep-blue-dust-a88ds8p1is not recreated. It was created 2026-10-11 and has never served a query.
Pending migrations (production is behind the repo)
production has applied migrations only through 20260425000000_email_tracking (applied 2026-04-28). Five newer migrations in the repo have not been applied to production, although staging has them:
20260503000000_add_verification_identifier_index20260527230500_add_billing_tables20260528213000_add_user_addons20260629000000_add_session_active_organization20260710000000_add_better_auth_plugin_tables
All five are additive (new tables, nullable columns, indexes, and foreign keys on the new tables). The plan applies them to the new database after the restore and before the cutover, so the new database goes live at the current schema.
Separate from the migration: if the deployed Worker already uses the Better Auth plugins (JWKS, passkeys, OAuth, API keys) or billing add-ons, those code paths are failing against the current production schema today. Check the Worker’s error logs.
flowchart LR
A[Create AWS project] --> B[Dump from Azure production]
B --> C[Restore into AWS]
C --> D[Apply 5 pending migrations]
D --> E{Verify counts and schema}
E -->|ok| F[Cloudflare: update Hyperdrive and vars]
F --> G[Smoke test and confirm writes land on AWS]
G --> H[Re-enable caching, keep old project 7-14 days]
E -->|mismatch| B
G -->|failure| R[Rollback: repoint Hyperdrive to Azure]
Before you start
- A terminal with PostgreSQL 17 client tools (
pg_dump --versionmust report 17 or newer) and the repo checked out with Deno available. - Neon Console access as an admin of the
Bloqr Systemsorganization. - Cloudflare dashboard access to Hyperdrive and the
bloqr-backendWorker. - A quiet time. Avoid Wednesdays 09:00-10:00 UTC, the old project’s maintenance window.
- Decide where the dump file lives: an encrypted local disk, never the repo, never a shared drive. It contains user emails and credential hashes.
- Do not paste connection strings into chat, tickets or logs. Set them with
read -sor from a password manager.
Step 0: Re-verify the source (read-only, 2 minutes)
In the Neon Console SQL Editor, select project bloqr-db, branch production, database adblock-compiler:
-- Anything beyond neondb_owner here must be accounted for before restoring with --no-acl.SELECT DISTINCT grantee FROM information_schema.role_table_grantsWHERE table_schema = 'public' AND grantee <> 'neondb_owner';
-- Expect only plpgsql.SELECT extname FROM pg_extension;
-- Exact row counts, compare to the table above.SELECT table_name, (xpath('/row/c/text()', query_to_xml(format('select count(*) as c from %I.%I', table_schema, table_name), false, true, '')))[1]::text::bigint AS exact_rowsFROM information_schema.tablesWHERE table_schema = 'public' AND table_type = 'BASE TABLE'ORDER BY exact_rows DESC, table_name;If the grantee query returns rows or the extension list has anything besides plpgsql, stop and revisit the role and extension plan.
Step 1: Create the AWS project
In the Neon Console, New project:
| Setting | Value |
|---|---|
| Organization | Bloqr Systems |
| Region | AWS US East 1 (N. Virginia) (aws-us-east-1) |
| Postgres version | 17 (do not combine a version upgrade with this move) |
| Project name | bloqr-db-aws while both projects exist. After the cutover, rename the old project bloqr-db-azure-old and, if you want the original name back, the new one bloqr-db. |
| Database name | adblock-compiler |
| Database owner | neondb_owner (the default role) |
Then match the old project’s settings under Settings:
| Setting | Old value | New project |
|---|---|---|
| Compute (read/write) | 1 to 4 CU, suspend after 10 minutes | Same |
| History retention | 6 hours | Same (raise it if the plan allows and you want a longer restore window) |
| Snapshot schedule | Daily (kept 5 days), weekly (35 days), monthly (30 days) | Same |
| Maintenance window | Wednesdays 09:00-10:00 UTC | Same |
| IP Allow | None | None |
| Logical replication | Enabled (unused) | Leave disabled |
| Data API, Neon Auth | Data API on (unused); Auth off | Leave both off |
| Read replica | Present (unused) | Do not create |
Record the new project ID and the new endpoint hostnames.
Step 2: Get two connection strings per project
In the Console, click Connect on each project’s production branch, select database adblock-compiler and role neondb_owner.
- Direct (untick Connection pooling): use for
pg_dump,pg_restoreand migrations. Neon says not to run these over a pooled connection. - Pooled (host contains
-pooler): use for Hyperdrive.
Source direct host is ep-winter-term-a8rxh2a9.eastus2.azure.neon.tech.
Step 3: Dump and restore
# Enter the URLs without echoing them. The password never appears in shell history.read -rs SRC_DIRECT_URL; export SRC_DIRECT_URLread -rs DST_DIRECT_URL; export DST_DIRECT_URL
pg_dump --version # must be 17 or newer
pg_dump -Fc -v --no-owner --no-acl -f bloqr-adblock-compiler.dump "$SRC_DIRECT_URL"pg_restore -v --no-owner --no-acl --exit-on-error -d "$DST_DIRECT_URL" bloqr-adblock-compiler.dump--no-owner --no-acl makes every restored object owned by the connecting role (neondb_owner) and skips grants. That is correct here because neondb_owner is the only role in use. --exit-on-error stops at the first problem instead of leaving a half-restored database.
Expected: both commands finish in well under a minute (an estimate for ~10 MB).
Rehearse first. Run steps 3 and 4 once end to end against the new project, verify, and only then repeat the dump and restore for the real cutover. Restore into an empty database; to redo, drop and recreate adblock-compiler in the Console, or reset the project.
Step 4: Apply the five pending migrations to the new database
From the repo root, pointing the Prisma tooling at the new direct URL. This runs locally and needs no GitHub secrets:
DIRECT_DATABASE_URL="$DST_DIRECT_URL" deno task db:migrateExpected: five migrations applied, none failed. All five are idempotent (IF NOT EXISTS) or create new objects.
Step 5: Verify the new database
Run in the new project’s SQL Editor (adblock-compiler):
SELECT count(*) AS applied_migrations FROM _prisma_migrations; -- expect 14SELECT extname FROM pg_extension; -- expect plpgsql onlySELECT DISTINCT tableowner FROM pg_tables WHERE schemaname = 'public'; -- expect neondb_owner onlySELECT sequencename, last_value FROM pg_sequences; -- compare with the sourceThen re-run the exact row-count query from step 0 on both databases and compare. Counts for the 11 populated tables must match the source (allowing for sessions and deployment_counter drifting between the two readings; _prisma_migrations will be 14 on the new side). The set of tables should equal the staging branch of the old project.
Do not proceed until the counts match.
Step 6: Cloudflare cutover
Do these in order.
-
Disable Hyperdrive query caching (dashboard: Storage & databases, Hyperdrive,
hyperdrive-adblockdb-neon-prod, edit). Caching is currently on, and cached reads could return old-database results briefly after the switch. -
Update the Hyperdrive origin in the same screen:
- Host: the new pooled host (contains
-pooler, ends inaws.neon.tech) - Port:
5432 - Database:
adblock-compiler - User:
neondb_owner - Password: the new project’s
neondb_ownerpassword
The Hyperdrive ID stays
800f7e2edc86488ab24e8621982e9ad7, sowrangler.tomland the Worker code need no change.CLI equivalent, if preferred (the repo rule is
deno task wrangler, nevernpx wrangler):Terminal window deno task wrangler hyperdrive update 800f7e2edc86488ab24e8621982e9ad7 \--origin-url "<new pooled URL>" - Host: the new pooled host (contains
-
Update Worker variables and secrets (dashboard: Workers & Pages,
bloqr-backend, Settings, Variables and Secrets):Name Action NEON_PROJECT_IDSet to the new project ID. It drives the /admin/neon/*handlers; if forgotten, they keep reporting on the old project.NEON_DATABASE_URLIf it exists, set it to the new direct URL (or remove it). It is used by the block-list and Radar-sync code ( neonApiService). Note that neither database holds themaster_block_listtables that code queries, so check whether this secret is set and what it points to.NEON_API_KEYNo change (account-scoped). Confirm it can see the new project in the admin Neon panel. DATABASE_URL,DIRECT_DATABASE_URLThe Worker reads the database through the HYPERDRIVEbinding and does not read these. Update them only if you use them elsewhere (local tooling, scripts).Variable and secret edits create a new Worker version automatically. No
wrangler deployis required for a Hyperdrive-only change.
Step 7: Smoke test
/api/health reports db_name: adblock-compiler for both the old and the new database, so it cannot tell you which one is live. Confirm by watching writes land on the new project:
-
GET /api/healthreturns healthy. (Thehyperdrive_hostfield is informational; do not rely on it to prove the origin.) - Sign in through the app. This creates a row in
sessions. - In the new project’s SQL Editor:
SELECT count(*), max(created_at) FROM sessions;shows the new session. - In the old project: the same query shows no new row.
- Create or use an API key, and run a compile from the app.
- Admin panel Neon section shows the new project.
- Re-enable Hyperdrive query caching.
Rollback
Until the new database receives real writes, rollback is: set the Hyperdrive origin back to the old pooled host and password (keep them handy), and restore the NEON_PROJECT_ID and NEON_DATABASE_URL values. After users write to the new database, rolling back discards those writes. In beta that is accepted, but decide before you move on from step 7.
After the cutover
- Recreate branches from the new
production:staging, thendev/jayson(child ofstaging). Protect them if you want parity with the old project. - Watch the Worker logs and Neon’s monitoring for a day.
- Keep the old project 7 to 14 days, then delete it in the Console. Deleting is irreversible and stops Azure storage charges.
- Securely delete the dump file (
shred -uor your platform’s equivalent) and clear the exported environment variables. - Rotate
neondb_owneron the new project once everything works. The password passed through your terminal during the migration. - Open a small docs/code cleanup PR (not part of the cutover): the Smart Placement comment at
wrangler.toml:293(“near Neon Azure East US 2”), theeastus2.azurehostnames inworker/handlers/health.test.tsand other test fixtures,.env.example, and the Neon pages underdocs/database-setup/anddocs/admin/.
Execution log
| Date (UTC) | Step | Result |
|---|---|---|
| 2026-10-11 | Step 1: create the AWS project | Done. Project bloqr-db-aws (steep-rice-35228530), aws-us-east-1, Postgres 17, org Bloqr Systems. Default branch production (br-empty-silence-b72w43hm), database adblock-compiler owned by neondb_owner, no other roles or databases. Compute 1-4 CU with a 10-minute suspend, history retention 6 hours, maintenance window Wednesday 09:00-10:00 UTC, logical replication off. Snapshot schedule set to daily (5 days), weekly (35 days), monthly (30 days). The branch is not yet protected; protect it after the restore. |
| 2026-10-11 | Schema | Done. All 14 prisma/migrations/*/migration.sql files replayed in order on the AWS database, each in one transaction (so the five migrations production was missing are included). _prisma_migrations created with Prisma’s own DDL. |
| 2026-10-11 | Schema drift found and fixed | Production has a waitlist table (7 rows, with an ip column) that no migration or Prisma model creates. It was recreated on AWS from production’s actual definition (BIGSERIAL id, unique email, two indexes). Column, index and constraint comparison of all other tables: no differences beyond the five pending migrations’ additions. |
| 2026-10-11 | Data copy | Done, via one-time logical replication, server to server. Temporary role migrate_repl and publication bloqr_migration on the Azure production database; subscription bloqr_migration on AWS. All 34 tables reached the ready state in under 3 seconds. |
| 2026-10-11 | Verification | 34 tables, 432 rows, 0 mismatches: exact row counts and a content hash per table identical between Azure production and AWS (excluding the three columns added by migrations 10-14). |
| 2026-10-11 | Finish | Subscription dropped (slot dropped with it). Migrations 10-14 recorded in _prisma_migrations with the real SHA-256 of each file (14 of 14 finished). waitlist_id_seq set to 8 to match production. |
| 2026-10-11 | Source cleanup | Done. Publication dropped, grants revoked, migrate_repl role deleted. Azure production now has only Neon’s own wal_proposer_slot and wal_retention_slot, as before. |
| 2026-10-11 17:01-17:03 | Cutover | Done. neondb_owner password on AWS rotated. Hyperdrive 800f7e2edc86488ab24e8621982e9ad7 caching disabled, origin switched via the Cloudflare API to ep-summer-pine-b73vvmyj-pooler.c-13.us-east-1.aws.neon.tech:5432 (database adblock-compiler, user neondb_owner, new password), then caching re-enabled (connection limit unchanged at 60). The previous origin was ep-winter-term-a8rxh2a9-pooler.eastus2.azure.neon.tech. |
| 2026-10-11 | Smoke test | GET /api/health healthy (in-Worker DB latency 66-201 ms; 190 ms before the switch). GET /api/health/db-smoke reports table_count: 47, which only the AWS database has (Azure production had 34). Transaction counters during the test: Azure +11 (background), AWS +147. |
| 2026-10-11 | Branches | AWS production protected. staging (child of production) and dev/jayson (child of staging) created and protected. They contain a copy of production data. |
| 2026-10-11 17:32-17:36 | Landing Worker | Done. Dedicated bloqr_landing database created, populated and secured (see the section above); bloqr-landing DATABASE_URL repointed to it. An interim overwrite to adblock-compiler with neondb_owner lasted about 10 minutes and was replaced. |
| Remaining (updated 2026-10-11) | GitHub Actions secrets are now updated by the owner; merge the PRs once CI runs. The rest of this row is the original list: update the GitHub Actions secrets NEON_PROJECT_ID, DIRECT_DATABASE_URL, DIRECT_DATABASE_URL_STAGING and NEON_DATABASE_URL (CI migrations and branch workflows still target Azure). bloqr-backend itself needs no variable changes: it has neither NEON_PROJECT_ID nor NEON_DATABASE_URL set. Retain the Azure project 7-14 days, then delete with explicit approval. Rename the AWS project to bloqr-db if desired. |
The AWS database is live. The Azure project is untouched and kept as the rollback target.
Rollback (valid until real writes land on AWS): PATCH the Hyperdrive config origin back to the Azure pooled host with the Azure neondb_owner password (retrievable from the Neon Console for the old project).
Step 3 (dump and restore) was replaced by the logical replication above; the commands in step 3 remain as the fallback. Step 4 was done by replaying the migration files rather than deno task db:migrate; Prisma sees 14 of 14 applied.
Credential hygiene. The AWS neondb_owner password appeared in the working session while the copy was driven, so it was rotated immediately before the cutover. The rotated value now appears in that session too (it had to be passed to Hyperdrive). If you want it out of session history, rotate it once more in the Neon Console and set the new value on the Hyperdrive origin in the Cloudflare dashboard.
Second database consumer: the bloqr-landing Worker (resolved)
Found after the cutover. The Cloudflare account has a second Worker, bloqr-landing (separate repo BloqrAI/bloqr-landing), that connected to the Azure adblock-compiler database directly with its own DATABASE_URL secret (not through Hyperdrive; only one Hyperdrive config exists). It used the database for waitlist signups, a /config endpoint reading site_config, and its own Better Auth, blog and admin features.
Why /config returned 500: site_config is not created by any deploy. It comes from manually run scripts in the landing repo (scripts/migrate-site-config.ts, migrate-better-auth.ts, migrate-blog-posts.ts, migrate-email-schema.ts), which had never been run against adblock-compiler. The landing Worker’s tables (site_config, user, session, blog_posts) therefore never existed there, and its account and verification tables would have collided with the compiler’s differently shaped tables of the same names. (scripts/migrations/001_email_db.sql is SQLite/D1 syntax and belongs to a D1 database, not Postgres.)
Correction. An earlier version of this section said the landing Worker’s failing queries did not reach the Azure project. That was wrong: Postgres statistics are updated lazily, and the Azure rollback counter did rise by 3 shortly after my three test requests.
Resolution (2026-10-11): the two domains now have separate databases, as the owner directed.
- Created database
bloqr_landingin the AWS project (productionbranch) and applied the DDL from the landing repo’s own scripts:site_config(created empty, because the script’s seed values are stale andgetConfig()prefers database rows over its defaults), Better Authuser/session/account/verification,blog_posts, andwaitlist(production’s shape plusemail_message_id). - Copied the 7
waitlistrows with ids and timestamps preserved (identical content hash on both sides) and setwaitlist_id_seqto 8. - Created role
landing_appwith plain SQL and strict attributes (noneon_superuser,CREATEROLE,BYPASSRLSorREPLICATION; roles created through Neon’s API get all of those). Verified with Postgres privilege checks: no privileges on any compiler table (users,api_keys,account, …), full CRUD on the 7 landing tables, no DDL. - Set the Worker’s
DATABASE_URLsecret to thelanding_apppooled connection string forbloqr_landing.GET https://bloqr.dev/confignow returns 200{}(was 500) and the Worker logged no errors afterwards.
Follow-ups (orphaned waitlist table in adblock-compiler, landing repo documentation, stale seeds, credential rotation) are tracked in issue #2300.
Post-cutover hardening (2026-10-11)
Done after the cutover, directly in Neon and Cloudflare because GitHub Actions was unavailable (billing).
Runtime role: compiler_app replaces neondb_owner
The compiler runtime no longer connects as the database owner. Role compiler_app was created with plain SQL (not through Neon’s API, which gives every role neon_superuser, CREATEROLE, BYPASSRLS and REPLICATION):
NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS,LOGIN.CONNECTonadblock-compiler;USAGEon schemapublic;SELECT, INSERT, UPDATE, DELETEon all tables andUSAGE, SELECT, UPDATEon all sequences inpublic; matchingALTER DEFAULT PRIVILEGESso future tables are covered. No DDL.- Hyperdrive
800f7e2edc86488ab24e8621982e9ad7origin user changed fromneondb_ownertocompiler_app(about 18:01 UTC, via the Cloudflare API; thepasswordfield is write-only and not settable from the dashboard tool). - Verified:
GET /api/health/db-smokereturns 200 (47 tables) and the Worker logged nopermission deniedor database errors across the 19:00 UTC cron. - Rollback:
PATCHthe Hyperdrive origin user back toneondb_owner.
neondb_owner is now needed only for migrations and CI (direct connection). landing_app is the equivalent role for bloqr_landing.
Test branches rebuilt from production
staging was reset from production, and dev/jayson was deleted and recreated as its child (new branch id, new endpoint), so both match production exactly. A fingerprint query run on all three branches returned identical hashes for roles and attributes, grants, default privileges, columns, indexes, constraints, extensions, sequences and data, for both adblock-compiler (47 tables, 437 rows) and bloqr_landing (7 tables). Role passwords come across with the branch and equal production’s. Neon Data API and Neon Auth are enabled per branch and were not copied. Test-branch compute is deliberately smaller (0.25-2 CU, 300 s suspend).
Neon project settings
| Setting | Value |
|---|---|
Point-in-time restore window (history_retention_seconds) | raised from 6 hours (21600) to 7 days (604800) |
| Snapshot schedule (production) | daily 04:00 (kept 5 days), weekly (kept 35 days), monthly (kept 30 days) |
| Branch protection | production, staging, dev/jayson protected |
| Production compute | 1-4 CU autoscaling, suspends after 600 s idle |
| Maintenance window | Wednesday 09:00-10:00 |
API keys
- GitHub Actions
NEON_API_KEY: project-scoped key forbloqr-db-aws, used by branch workflows. bloqr-backendNEON_API_KEYandNEON_PROJECT_ID: a separate project-scoped key plus the project id, both set as Worker secrets (used by the/admin/neon/*routes). Separate keys limit the blast radius and allow independent rotation.- Credentials that appeared in the working session (
neondb_owner,compiler_app,landing_app) were rotated by the owner afterwards.
Cloudflare findings from the post-migration review
- Observability kept turning itself off. The backend, frontend and mail
wrangler.tomlfiles declared[observability.logs]and[observability.traces]but not the parent[observability] enabled = true, so everywrangler deployreset the master switch. Fixed in the wrangler files (branchclaude/wrangler-observability) and live for all Workers. Smart Placement was likewise pinned in the frontend, mail and tail configs. - Worker Cache (new
cache_optionssetting) is on forbloqr-docsonly. It is deliberately off for the backend, frontend and landing pending an audit of response cache headers (issue #2301). - Zone changes (final): Rocket Loader turned off on
bloqr.dev(it was on; it can interfere with the Angular and Astro bundles and Turnstile). Browser cache TTL onbloqr.devchanged from a fixed 4 hours to respect-origin-headers (the zone’s cache rules already respect origin). Minimum TLS raised to 1.2 onknightlocked.com. Unused queueimages-eventsdeleted.adblock-compiler-worker-queue(no consumer; fed only by an event notification on R2 bucketadblock-compiler-r2-storage) could NOT be deleted yet: Cloudflare refuses while it is an event-notification target, and the API token used here has no R2 access. Remove the bucket’s notification rule first (dashboard: R2 > bucket > Settings > Event notifications, orwrangler r2 bucket notification delete adblock-compiler-r2-storage --queue adblock-compiler-worker-queue), then delete the queue. DNSSEC onbloqr.devis active (enabled 2026-10-12). The registrar is Cloudflare, so the DS record is published to the registry automatically; nothing is added by hand anywhere else. Verified 2026-10-12 16:56 UTC:bloqr.devDS2371 13 2(algorithm 13, ECDSAP256SHA256; digest type 2, SHA-256) is returned by bothcloudflare-dns.comanddns.googleDNS-over-HTTPS with the AD (authenticated data) flag set, andbloqr.dev,api.,app.anddocs.all resolve (status 0, no SERVFAIL). Do not copy this DS to another registrar: a DS saved at GoDaddy for the wrong domain earlier the same day caused a brief SERVFAIL until it was removed. If the DS ever disappears, a validating resolver returns SERVFAIL for the whole zone, so check withcurl -s -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=bloqr.dev&type=DS'before and after any DNSSEC change. Other zones were not re-checked and are assumed to still have DNSSEC disabled.
Open questions
NEON_DATABASE_URLis confirmed dangling by the owner: it feeds block-list and Radar-sync code that queries tables (master_block_list, …) which exist in neither database. Verified after the cutover: it is not set on thebloqr-backendWorker at all (nor isNEON_PROJECT_ID). It exists only as a GitHub Actions secret used byneon-branch-create.yml.- The
waitlisttable is not under migration control, and stores visitor emails and IPs. It should be added toprisma/schema.prismawith a migration (written idempotently, since it already exists in production and now on AWS), and itsipcolumn reviewed against the Edge Data Export Policy. - Are the five pending migrations required by the currently deployed Worker? If yes, the affected features have been failing in production since those releases.
- Does anything outside this repo (a dashboard, a script, a teammate’s tooling) hold the old connection string or the Data API URL?