Agent skill

async-sync-advisor

Guides users on choosing between async and sync patterns for Lambda functions, including when to use tokio, rayon, and spawn_blocking. Activates when users write Lambda handlers with mixed workloads.

Stars 232
Forks 15

Install this agent skill to your Project

npx add-skill https://github.com/aiskillstore/marketplace/tree/main/skills/emillindfors/async-sync-advisor

SKILL.md

Async/Sync Advisor Skill

You are an expert at choosing the right concurrency pattern for AWS Lambda in Rust. When you detect Lambda handlers, proactively suggest optimal async/sync patterns.

When to Activate

Activate when you notice:

  • Lambda handlers with CPU-intensive operations
  • Mixed I/O and compute workloads
  • Use of tokio::task::spawn_blocking or rayon
  • Questions about async vs sync or performance

Decision Guide

Use Async For: I/O-Intensive Operations

When:

  • HTTP/API calls
  • Database queries
  • S3/DynamoDB operations
  • Multiple independent I/O operations

Pattern:

rust
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    // ✅ All I/O is async - perfect use case
    let (user, profile, settings) = tokio::try_join!(
        fetch_user(id),
        fetch_profile(id),
        fetch_settings(id),
    )?;

    Ok(Response { user, profile, settings })
}

Use Sync + spawn_blocking For: CPU-Intensive Operations

When:

  • Data processing
  • Image/video manipulation
  • Encryption/hashing
  • Parsing large files

Pattern:

rust
use tokio::task;

async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    let data = event.payload.data;

    // ✅ Move CPU work to blocking thread pool
    let result = task::spawn_blocking(move || {
        // Synchronous CPU-intensive work
        expensive_computation(&data)
    })
    .await??;

    Ok(Response { result })
}

Use Rayon For: Parallel CPU Work

When:

  • Processing large collections
  • Parallel data transformation
  • CPU-bound operations that can be parallelized

Pattern:

rust
use rayon::prelude::*;
use tokio::task;

async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    let items = event.payload.items;

    // ✅ Combine spawn_blocking with Rayon for parallel CPU work
    let results = task::spawn_blocking(move || {
        items
            .par_iter()
            .map(|item| cpu_intensive_work(item))
            .collect::<Vec<_>>()
    })
    .await?;

    Ok(Response { results })
}

Mixed Workload Pattern

rust
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    // Phase 1: Async I/O - Download data
    let download_futures = event.payload.urls
        .into_iter()
        .map(|url| async move {
            reqwest::get(&url).await?.bytes().await
        });
    let raw_data = futures::future::try_join_all(download_futures).await?;

    // Phase 2: Sync compute - Process with Rayon
    let processed = task::spawn_blocking(move || {
        raw_data
            .par_iter()
            .map(|bytes| process_data(bytes))
            .collect::<Result<Vec<_>, _>>()
    })
    .await??;

    // Phase 3: Async I/O - Upload results
    let upload_futures = processed
        .into_iter()
        .enumerate()
        .map(|(i, data)| async move {
            upload_to_s3(&format!("result-{}.dat", i), &data).await
        });
    futures::future::try_join_all(upload_futures).await?;

    Ok(Response { success: true })
}

Common Mistakes

❌ Using async for CPU work

rust
// BAD: Async adds overhead for CPU-bound work
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    let result = expensive_cpu_computation(&event.payload.data);  // Blocks async runtime
    Ok(Response { result })
}

// GOOD: Use spawn_blocking
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    let data = event.payload.data.clone();
    let result = tokio::task::spawn_blocking(move || {
        expensive_cpu_computation(&data)
    })
    .await?;
    Ok(Response { result })
}

❌ Not using concurrency for I/O

rust
// BAD: Sequential I/O
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    let user = fetch_user(id).await?;
    let posts = fetch_posts(id).await?;  // Waits for user first
    Ok(Response { user, posts })
}

// GOOD: Concurrent I/O
async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    let (user, posts) = tokio::try_join!(
        fetch_user(id),
        fetch_posts(id),
    )?;
    Ok(Response { user, posts })
}

Your Approach

When you see Lambda handlers:

  1. Identify workload type (I/O vs CPU)
  2. Suggest appropriate pattern (async vs sync)
  3. Show how to combine patterns for mixed workloads
  4. Explain performance implications

Proactively suggest the optimal concurrency pattern for the workload.

Expand your agent's capabilities with these related and highly-rated skills.

aiskillstore/marketplace

perigon-backend

Perigon ASP.NET Core + EF Core + Aspire conventions

232 15
Explore
aiskillstore/marketplace

perigon-agent

Pointers for Copilot/agents to apply Perigon conventions

232 15
Explore
aiskillstore/marketplace

perigon-angular

Angular 21+ standalone/Material/signal conventions for Perigon WebApp

232 15
Explore
aiskillstore/marketplace

fastapi-mastery

Comprehensive FastAPI development skill covering REST API creation, routing, request/response handling, validation, authentication, database integration, middleware, and deployment. Use when working with FastAPI projects, building APIs, implementing CRUD operations, setting up authentication/authorization, integrating databases (SQL/NoSQL), adding middleware, handling WebSockets, or deploying FastAPI applications. Triggered by requests involving .py files with FastAPI code, API endpoint creation, Pydantic models, or FastAPI-specific features.

232 15
Explore
aiskillstore/marketplace

context7-efficient

Token-efficient library documentation fetcher using Context7 MCP with 86.8% token savings through intelligent shell pipeline filtering. Fetches code examples, API references, and best practices for JavaScript, Python, Go, Rust, and other libraries. Use when users ask about library documentation, need code examples, want API usage patterns, are learning a new framework, need syntax reference, or troubleshooting with library-specific information. Triggers include questions like "Show me React hooks", "How do I use Prisma", "What's the Next.js routing syntax", or any request for library/framework documentation.

232 15
Explore
aiskillstore/marketplace

browser-use

Browser automation using Playwright MCP. Navigate websites, fill forms, click elements, take screenshots, and extract data. Use when tasks require web browsing, form submission, web scraping, UI testing, or any browser interaction.

232 15
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results