chore(db): drop legacy copilot_chats.messages JSONB column#4886
Conversation
Reads and writes are fully cut over to the normalized copilot_messages table (verified in production: no writes to the column in 24h, recently-active chats have empty JSONB while copilot_messages holds the transcript). Drop the dead column via drizzle migration 0225 and re-type CopilotChatDetailRow.messages as an assembled (non-column) field. Deploy notes: reconcile any chats where the JSONB still leads copilot_messages before applying, and pg_repack copilot_chats afterward to reclaim the ~5.7GB TOAST storage (DROP COLUMN is metadata-only).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview
Deploy order matters: reconcile any chats where JSONB still leads Reviewed by Cursor Bugbot for commit 0f4d158. Configure here. |
Greptile SummaryThis PR completes the migration of copilot chat transcript storage from a legacy
Confidence Score: 5/5Safe to merge once the pre-deploy reconciliation step from the PR description has been completed — the schema, Drizzle snapshot, journal, and application code are all consistent with the dropped column. All five changed files are internally consistent: the migration drops exactly the column removed from schema.ts, the Drizzle snapshot matches, and lifecycle.ts correctly assembles the transcript from copilot_messages instead of the now-gone column. No application code writes to or reads from the legacy column, and the two key read paths (getAccessibleCopilotChat, getAccessibleCopilotChatWithMessages) both call loadCopilotChatMessages before returning. No files require special attention. The operational pre-flight (reconcile script + pg_repack) is documented in the PR and is outside the diff. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant API as API Route
participant LC as lifecycle.ts
participant DB as copilot_chats
participant CM as copilot_messages
Note over DB: messages JSONB column dropped (0225)
Client->>API: GET /copilot/chat/:id
API->>LC: getAccessibleCopilotChatWithMessages(chatId, userId)
LC->>DB: SELECT (id, userId, title, ...) — no messages column
DB-->>LC: chat metadata row
LC->>CM: loadCopilotChatMessages(chatId)
CM-->>LC: PersistedMessage[] ordered by seq
LC-->>API: "{ ...chat, messages: PersistedMessage[] }"
API-->>Client: chat + assembled transcript
Client->>API: POST /copilot/chat/update-messages
API->>DB: UPDATE copilot_chats SET updatedAt, planArtifact, config
API->>CM: replaceCopilotChatMessages(chatId, messages)
CM-->>API: OK
API-->>Client: "{ success: true }"
Reviews (2): Last reviewed commit: "chore(db): drop legacy copilot_chats.mes..." | Re-trigger Greptile |
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0f4d158. Configure here.
Summary
copilot_chats.messagesJSONB column (~5.7GB, ~99% TOAST) now that all reads and writes are fully on the normalizedcopilot_messagestable.0225_greedy_ares.sql:ALTER TABLE "copilot_chats" DROP COLUMN "messages"+ drizzle snapshot/journal.CopilotChatDetailRow.messagesas an assembled (non-column) field since it no longer comes from the chat row.Production verification (before dropping)
copilot_chats.messageswrites in the last 24h (insights); recently-active chats have empty JSONB whilecopilot_messagesholds the transcript.messages-related read queriescopilot_messages, not the column.Deploy sequence (important)
copilot_messages(small tail of pre-dual-write chats) before applying this migration — otherwise those messages are lost.0225.pg_repack copilot_chatsafterward to actually reclaim the ~5.7GB (DROP COLUMN is metadata-only).Type of Change
Testing
Tested manually:
drizzle-kit generateproduced a clean single-statement migration;a2a_task.messagesuntouched.tscpasses (apps/sim + packages/db), 133 copilot/mothership tests pass, biome clean.Checklist