agentsclimarketplace

Async sync advisor

Skill aiskillstore/marketplace/skills/emillindfors/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.From its SKILL.md

Install
npx -y skills add aiskillstore/marketplace --skill async-sync-advisor

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.

SKILL.md

4.7 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

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:

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:

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:

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

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

// 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

// 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.

What ships with it: 1 file

17.4 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.