Back to Eliminating Waterfalls

Defer Await Until Needed

asyncawaitconditionaloptimization
28.0k🕒 2026-06-10Source ↗

Install this skill

npx skills add vercel-labs/agent-skills

Works across Claude Code, Cursor, Codex, Copilot & Antigravity

The Defer Await Until Needed pattern addresses performance bottlenecks caused by premature asynchronous execution. By delaying the resolution of promises until the specific point of consumption, you prevent unnecessary latency in execution paths that do not require those results. This is vital when dealing with conditional logic or early returns, where an application might otherwise wait for expensive I/O operations—such as database queries or external API calls—that never contribute to the final output. Aligning your await statements with the actual execution flow reduces total response time and minimizes resource consumption, ensuring that logic branches requiring fewer dependencies complete faster. This approach transforms linear, waterfall-heavy functions into efficient, demand-driven operations that only consume execution cycles exactly when they become mandatory for a task’s successful resolution.

When to Use This Skill

  • Functions with multiple early return guard clauses
  • Operations that only conditionally access external API results
  • Methods where expensive resource fetching occurs before validation
  • Services handling heavy payloads only for authorized users

How to Invoke This Skill

Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:

  • Refactor this function to remove unnecessary blocking
  • Optimize this async code for early returns
  • Stop fetching data if the condition fails early
  • Fix the waterfall performance in this request handler
  • Delay promise resolution until the result is required

What this skill does

  • Identifies unnecessary await blocks in conditional logic
  • Optimizes function response times for early returns
  • Reduces idle latency by delaying heavy I/O operations
  • Restructures asynchronous sequences to prioritize light paths
  • Prevents sequential blocking in branching control flow

When not to use it

  • When promises must be executed in parallel to improve performance
  • When subsequent operations depend on the result regardless of the branch taken

Example workflow

  1. Analyze the function for early return conditions
  2. Identify variables initialized via await that appear before these conditions
  3. Move await declarations inside the logical blocks that consume them
  4. Verify that the execution path remains correct for all branches
  5. Benchmark the performance difference for the early return case

Pitfalls & limitations

  • !Accidentally introducing race conditions if side effects are required
  • !Breaking logic if the deferred variable is needed in multiple sibling branches
  • !Over-fragmenting code readability for minor performance gains

FAQ

Does this technique always improve performance?
It improves performance when early returns are triggered frequently. If the deferred code is needed in almost every execution path, the net gain will be minimal.
Can I use this for all async calls?
No, only move awaits that are conditional. If the data is always needed, you might actually prefer running them in parallel using Promise.all.
Will this make my code harder to read?
It may increase vertical length if poorly implemented. However, it usually improves clarity by explicitly showing when and why data is fetched.

How it compares

While manual optimization requires identifying and relocating lines by hand, this skill automates the dependency analysis and safe movement of await statements to ensure functional parity.

Source & trust

28k stars🕒 Updated 2026-06-10
📄 Full skill instructions — original source: vercel-labs/agent-skills
## 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.

How to Use This Skill Unit

Option A: Project-Specific (Recommended)

  1. Click "Download" above
  2. In your project, create the directory: .agent/skills/async-defer-await/
  3. Save the file as SKILL.md
  4. The agent will automatically discover the skill based on its description.

Option B: Global Installation (All Agents)

Save the file to these locations to make it available across all projects:

  • Claude Code: ~/.claude/skills/vercel-labs/agent-skills/async-defer-await/SKILL.md
  • Cursor: ~/.cursor/skills/vercel-labs/agent-skills/async-defer-await/SKILL.md
  • Antigravity: ~/.gemini/antigravity/skills/vercel-labs/agent-skills/async-defer-await/SKILL.md

🚀 Install with CLI:
npx skills add vercel-labs/agent-skills

Read the Master Guide: Mastering Agent Skills

Recommended Rules

View more rules

Recommended Workflows

View more workflows

Recommended MCP Servers

View more MCP servers

Take It Further

Maximize your productivity with these powerful resources

📋

Define Your Standards

Set up coding standards to ensure this workflow produces consistent, high-quality results.

Browse Rules Library
📖

Master Workflows

Learn how to create custom workflows, use Turbo Mode, and build your automation library.

Complete Guide

How to use this Skill in Claude Code & Cursor

For Claude Code (CLI)

To use this skill in Claude Code, copy the rule content into your project's custom instructions or follow our Add-Skill CLI guide. This ensures Claude follows your standards during every code generation.

For Cursor & Windsurf

For Cursor or Windsurf, individual skills are best used in the "Rules for AI" section. This specific unit helps the agent avoid eliminating waterfalls issues, leading to cleaner, more efficient code.

Why the skill format matters: the standardized Agent Skills format lets your AI agent load detailed instructions only when they are relevant, keeping your prompt clean while improving results.

Source & attribution

This skill is categorized under Eliminating Waterfalls and is published by Vercel Engineering, maintained in vercel-labs/agent-skills.

← Browse All Agent Skills
Sponsored AI assistant. Recommendations may be paid.