Follow/Unfollow Transactional Logic
Why it matters
Non-transactional follow mutations create race conditions (CWE-362) that permanently corrupt follower counts — a user can end up showing 5,000 followers in their count column while the actual follows row count is 4,200. Worse, without a unique constraint on (followerId, followedId), concurrent double-taps produce duplicate follow rows that inflate counts and break feed queries. Self-following bypasses are both a data integrity failure and an embarrassing product defect. These are not edge-case concerns: follow endpoints are hammered at scale, making TOCTOU collisions routine.
Severity rationale
Critical because non-transactional follow mutations cause irreversible count corruption under concurrent load, and absent unique constraints allow data model violations that cascade into feed and notification logic.
Remediation
Add @@unique([followerId, followedId]) to your Prisma Follow model to enforce deduplication at the database level, then wrap every follow mutation in a db.$transaction that updates both the relationship and the denormalized counts atomically.
// app/api/users/[id]/follow/route.ts
export async function POST(req: Request, { params }: { params: { id: string } }) {
const userId = getCurrentUserId()
if (userId === params.id) {
return Response.json({ error: 'Cannot follow yourself' }, { status: 400 })
}
await db.$transaction([
db.follow.create({ data: { followerId: userId, followedId: params.id } }),
db.user.update({ where: { id: userId }, data: { following_count: { increment: 1 } } }),
db.user.update({ where: { id: params.id }, data: { followers_count: { increment: 1 } } })
])
return Response.json({ success: true })
}
The unique constraint ensures a duplicate follow throws a Prisma P2002 error before the transaction commits, eliminating the race window entirely.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Social Features & Engagement Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-362 — Concurrent Execution Using Shared Resource with Improper Synchronization (Race Condition)
- cwe · CWE-284 — Improper Access Control
- iso-25010:2011 · functional-suitability — Functional Correctness
Taxons
History
- 2026-04-18·v1.0.0·Initial import from community-social-engagement·automated