Unlock Your Python Backend Career: Build 30 Projects in 30 Days. Join now for just $54

Are async blocks dead? Introducing async closures (rust 1.85)

by Ugochukwu Chizaram Omumusinachi

.

Updated Wed Mar 12 2025

.
Are async blocks dead? Introducing  async closures (rust 1.85)

We just saw the official release of Rust's 1.85 version, and a lot of wow changes came with it, one of them would be async closures.

This new feature has caused a lively debate in the Rust community: Are async blocks, a staple of Rust’s async ecosystem, now obsolete? Are they useless?

As of February 28, 2025, the answer seems clear—async blocks are far from dead. Instead, they coexist with async closures, each serving unique purposes in Rust’s ever-evolving toolkit for non-blocking code.

Looking into what this means for developers and why both features remain relevant.

The Basics: Async Blocks vs. Async Closures

To understand what is going on, we first need to understand the two key terms. Async blocks, written as async { ... }, have been around since Rust’s async/await syntax debuted in version 1.39

They create a single, anonymous future—essentially a one-and-done piece of asynchronous work, just like a normal code block {//code logic} but with async privileges.

Here’s a simple example:

let future = async {
    println!("Running an async block!");
};
future.await;

They’re straightforward, perfect for encapsulating a specific task without reusable structure.

Now, async closures are stabilized in Rust 1.85, with the syntax async |param| { ... }. These are callable async functions that return a new future each time they’re invoked.

For example:

let closure = async |message: &str| {
    println!("Message: {}", message);
};
closure("Hello, Rust!").await;

Unlike async blocks, async closures can take parameters and be reused.

This makes them ideal for scenarios where you want flexibility and callability.

So what’s the big new with them?

Async closures address two long-standing limitations in Rust’s async model.

  • First, they enable higher-ranked async function signatures, like think passing async functions as arguments to other functions.

  • Second, they allow futures to borrow from captured variables more naturally, like you with a normal closure, enhancing ergonomics. For example, a situation where you need to process multiple tasks dynamically:


let tasks = vec![
    async |url: &str| { println!("Fetching {}", url); },
    async |path: &str| { println!("Reading {}", path); },
];
for task in tasks {
    task("example.com").await;
}

This kind of reusable, parameterized async logic was difficult before Rust 1.85, but thanks to async closures, it is now fixed.

Are Async Blocks Obsolete?

So, with async closures in the picture, do we still need async blocks? Absolutely. The two features aren’t rivals—they’re teammates. Async blocks shine in simplicity. When you need a one-off future, like fetching data in a single function, they’re the go-to:

async fn fetch_data() -> String {
    let response = async {
        // Simulate an HTTP request
        "Data received".to_string()
    }.await;
    response
}

No parameters, no reuse, OTOH, and async closures, by contrast, are overkill for such cases but excel in complex scenarios, like event handlers or callbacks requiring repeated execution. So you see, they are just different things, not really enemies.

What does the community think, and what does this mean for you as a developer

The Rust community agrees. Discussions on forums and insights from sources like the Rust Changelogs for 1.85.0 suggest that async blocks remain fundamental. They’re not going anywhere; they’re just sharing the stage with a more versatile variant.

Practical Implications for Developers

For Rust developers, this means more options, not a replacement. Use async blocks for quick, inline async tasks—think of them as the lightweight, single-use tool in your kit.

Reach for async closures when you need reusable async logic, especially in higher-order functions or when passing async behavior around. Here’s a quick guide:

  • Async Blocks: One-time futures, simple operations (e.g., inline data fetching).

  • Async Closures: Reusable async functions and parameterized tasks (e.g., dynamic task processing).

Now that you have an idea of the all-new async closures in rust, you might want to update your code base to reflect this beautiful change, increase your readability, and remove those weird async closure walkarounds like wrapping an async block in a rust closure. If you have any issues understanding this, feel free to reach out to me on my LinkedIn if you need more clarification.

P.S. This was what I meant by an async closure walkaround; it was used before the stabilization of async closures.

In the code, you create a normal closure, but the closure's block is async'ed, and a move is added so you do not have borrow issues; instead, all the values used are used once.

let async_closure_walkaround = || async move {};

Play around with this feature so you get a feel for it. See the Rust playground for more practice.

Course image
Become a Rust Backend Engineeer today

All-in-one Rust course for learning backend engineering with Rust. This comprehensive course is designed for Rust developers seeking proficiency in Rust.

Start Learning Now

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board

Backend Tips, Every week

Backend Tips, Every week