Skip to main content

Async Defer Await

Source: .agents/references/coding-standard/vercel-react-best-practices/rules/async-defer-await.md

Metadata

  • title: Defer Await Until Needed
  • impact: HIGH
  • impactDescription: avoids blocking unused code paths
  • tags: async, await, conditional, optimization

Content

Defer Await Until Needed

Move await operations into the branches where they're actually used to avoid blocking code paths that don't need them.

Incorrect (blocks both branches):

async function handleRequest(userId: string, skipProcessing: boolean) {
const userData = await fetchUserData(userId)

if (skipProcessing) {
// Returns immediately but still waited for userData
return { skipped: true }
}

// Only this branch uses userData
return processUserData(userData)
}

Correct (only blocks when needed):

async function handleRequest(userId: string, skipProcessing: boolean) {
if (skipProcessing) {
// Returns immediately without waiting
return { skipped: true }
}

// Fetch only when needed
const userData = await fetchUserData(userId)
return processUserData(userData)
}

Another example (early return optimization):

// Incorrect: always fetches permissions
async function updateResource(resourceId: string, userId: string) {
const permissions = await fetchPermissions(userId)
const resource = await getResource(resourceId)

if (!resource) {
return { error: 'Not found' }
}

if (!permissions.canEdit) {
return { error: 'Forbidden' }
}

return await updateResourceData(resource, permissions)
}

// Correct: fetches only when needed
async function updateResource(resourceId: string, userId: string) {
const resource = await getResource(resourceId)

if (!resource) {
return { error: 'Not found' }
}

const permissions = await fetchPermissions(userId)

if (!permissions.canEdit) {
return { error: 'Forbidden' }
}

return await updateResourceData(resource, permissions)
}

This optimization is especially valuable when the skipped branch is frequently taken, or when the deferred operation is expensive.

For await getFlag() combined with a cheap synchronous guard (flag && someCondition), see Check Cheap Conditions Before Async Flags.