Your first review
A walkthrough of what happens when Bedrock reviews a real migration — using a many-to-many user/organization change as the worked example.
The change
Suppose your app started with each user belonging to a single organization (users.organization_id) and you now want to support users belonging to many.
prisma
model User {
id String @id @default(cuid())
- organizationId String
- organization Organization @relation(fields: [organizationId], references: [id])
+ memberships Membership[]
}
+ model Membership {
+ id String @id @default(cuid())
+ user User @relation(fields: [userId], references: [id])
+ userId String
+ organization Organization @relation(fields: [organizationId], references: [id])
+ organizationId String
+ role Role @default(MEMBER)
+ @@unique([userId, organizationId])
+ }What Bedrock detects
- Relationship cardinality changed:
1:N→N:N. - A foreign key column on
usersis implicitly removed. - Every read of
user.organizationIdin your codebase will break.
Why this is high-risk
This is not a simple additive change. It rewrites a permission boundary. Auth, billing, audit logs, and analytics events all likely read
users.organization_id directly. A clean drop will take production down.The plan Bedrock writes
sql
-- Phase 1 — ships immediately (additive, zero-downtime)
CREATE TABLE memberships (
id text PRIMARY KEY,
user_id text NOT NULL REFERENCES users(id),
organization_id text NOT NULL REFERENCES organizations(id),
role text NOT NULL DEFAULT 'member',
UNIQUE (user_id, organization_id)
);
-- Phase 2 — backfill in batches of 1000 with retries
INSERT INTO memberships (id, user_id, organization_id, role)
SELECT gen_random_uuid()::text, id, organization_id, 'owner'
FROM users
WHERE organization_id IS NOT NULL
ON CONFLICT DO NOTHING;
-- Phase 3 — flip reads behind feature flag (app code change, no SQL)
-- Phase 4 — soak 14 days, verify zero divergence
-- Phase 5 — drop users.organization_id (separate PR)The PR comment
text
Bedrock / migration safety · review
Verdict review
Risk score 71 / 100
Type relationship cardinality change
Top issues
1. users.organization_id removed in same migration as memberships table
→ recommend a separate cleanup migration after a 14-day soak.
2. References to user.organizationId found in src/auth/, src/billing/, src/api/
→ flip reads behind a feature flag before destructive cleanup.
3. No backfill detected. Existing users will lose organization context on deploy.
Open the full report → bedrock.dev/r/3a7f9c1b