Synchronous in-line notification creation ties the success of a user action (like, follow, comment) to the reliability of a secondary side-effect. If the notification INSERT fails — due to a database timeout, connection exhaustion, or a schema constraint — the user sees an error for an action that actually succeeded. Under ISO 25010:2011 reliability, the primary mutation and the downstream notification are separate concerns with different fault tolerances. Coupling them in one request also adds latency: notification creation may involve email dispatch or push webhook calls, blocking the response for hundreds of milliseconds.
High because synchronous notification coupling turns transient notification failures into visible errors on high-frequency user actions, degrading the core interaction loop.
Move notification creation out of the request handler and into an async queue using Inngest, BullMQ, or a Vercel background function. The primary mutation returns immediately; the queue worker handles notification delivery independently.
// app/api/posts/[id]/like/route.ts
import { inngest } from '@/lib/inngest'
export async function POST(req: Request, { params }: { params: { id: string } }) {
const userId = getCurrentUserId()
const like = await db.like.create({ data: { userId, postId: params.id } })
// Fire-and-forget — notification failure does not affect the response
await inngest.send({
name: 'notification/post.liked',
data: { likerId: userId, postId: params.id }
})
return Response.json({ success: true })
}
The Inngest function handles retries and dead-lettering without coupling them to the HTTP response cycle.
ID: community-social-engagement.notifications.event-trigger-architecture
Severity: high
What to look for: Enumerate all relevant files and Examine how notifications are created when users interact (e.g., when post is liked, user is followed, comment is posted). Look for a decoupled architecture: database triggers, event queue (Bull, Bree, Inngest), or async event bus. Verify that notification creation doesn't block the response to the user action. Check that if the notification service fails, the main action (like, follow, etc.) still succeeds.
Pass criteria: At least 1 implementation must be present. Notifications are triggered asynchronously, decoupled from the main request. Notification failure doesn't cause the user action to fail. Evidence: async queue, database trigger, or event bus in use.
Fail criteria: Notifications are created synchronously in the same request. If notification creation fails, the entire action fails.
Skip (N/A) when: Platform has no notifications feature.
Detail on fail: "Like endpoint synchronously creates notification before returning — if DB insert fails, user sees error even though like was recorded" or "No async notification processing; all notifications are inline"
Remediation: Decouple notifications with async processing:
// app/api/posts/[id]/like/route.ts
import { queueNotification } from '@/lib/queue'
export async function POST(req: Request, { params }) {
const userId = getCurrentUserId()
const postId = params.id
// Create like (synchronous, must succeed)
const like = await db.like.create({
data: { userId, postId }
})
// Queue notification (async, ok if it fails)
await queueNotification({
type: 'post_liked',
userId: like.userId,
targetId: postId,
recipientId: await getPostOwnerId(postId)
})
return Response.json({ success: true })
}
// Queue worker processes notifications
async function processNotificationQueue() {
const job = await queue.getNextJob()
await createNotification(job.data)
}