- Published on
Polkadot 2.0 Tutorial: Upgrading a Parachain with Async Backing
Language: English
Author: Dustin
Level: Imtermidiate
What is Async Backing?
Twice as Fast: Parachain block time is cut in half, from 12 seconds down to 6 seconds.
More Independent: Parachains can build blocks continuously without having to wait for the Relay Chain each time.
Better Performance: This results in a faster, more efficient network that can handle more transactions.
Prerequisites
Before starting, ensure your development environment is correctly configured.
1. Rust Toolchain 🦀
Compatibility between your Rust version and the Polkadot SDK is critical. Build failures are often due to a toolchain mismatch.
💡 Tip: The Polkadot SDK frequently requires a specific nightly Rust toolchain. To prevent compatibility issues, install and set the recommended version:
rustup default nightly-2024-06-12
2. Relay Chain Binary & Zombienet ⛓️
A local Relay Chain and the Zombienet testing orchestrator are required. A helper script is often provided to build these components.
./scripts/zombienet.sh build
This script will output the necessary binaries into two new folders:
bin-stable2407-1
: Contains the Polkadot Relay Chain binary.zombienet-macos-arm64
: Contains the Zombienet binary (your OS may differ)..
⚠️ Important: This build process is resource-intensive and can take 30-40 minutes.
3. Zombienet CLI 🧟
Install the Zombienet CLI globally for easy access to its commands.
npm i @zombienet/cli@latest -g
Phase 0: Code Configuration for Async Backing
Your parachain's runtime and node logic must be conditionally compiled using feature flags to support both synchronous and asynchronous modes.
- Normal (Synchronous) Parachain Code:
#[cfg(not(feature = "async-backing"))] // ... synchronous logic ...
- Async Backing Parachain Code:
#[cfg(feature = "async-backing")] // ... async backing logic ...
ℹ️ Note: For a detailed guide on the required code changes, refer to the official Polkadot documentation on configuring async backing.
Link existing pre-configured project: https://github.com/CocDap/parachain-async-backing
Clone the project
git clone https://github.com/CocDap/parachain-async-backing
cd parachain-async-backing
Phase 1: Launch the Synchronous Parachain
First, we build and launch the parachain in its original, synchronous state (12-second block time).
1. Build the "Old" Binary
Compile the parachain node without the async-backing
feature.
cargo build --release
This creates the initial client executable at /target/release/generic-template-node
, which we'll refer to as the "old binary."
2. Launch the Network
Use Zombienet to spawn your local testnet, consisting of a Relay Chain and your parachain.
zombienet --provider native spawn zombienet-config/devnet.toml

3. Verify the Initial State
Connect to your parachain via Polkadot-JS Apps to confirm it's running correctly.
- RPC Endpoint:
ws://127.0.0.1:8833
- Initial State Check:
- The runtime
spec_version
should be 1. - The target block time will be 12 seconds.
- The runtime

Phase 2: Prepare the Async Backing Upgrade
Next, we'll prepare the new runtime and client binary required for the upgrade.
spec_version
1. Increment the Runtime A runtime upgrade is only accepted by the network if the spec_version
is greater than the current version. Update this in your runtime's constants file.
// src/constants.rs
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("template-parachain"),
impl_name: create_runtime_str!("template-parachain"),
authoring_version: 1,
spec_version: 2, // INCREASE HERE
impl_version: 0,
apis: apis::RUNTIME_API_VERSIONS,
transaction_version: 1,
state_version: 1,
};
2. Build the "New" Binary
In a new terminal window, build the node again, but this time enable the async-backing
feature flag. This compiles the new logic into the client.
⚠️ Keep the Zombienet network running in the other terminal!
cargo build --release --features async-backing
This command creates the "new binary" with async backing capabilities, overwriting the old file at /target/release/generic-template-node
.
Phase 3: Execute the Runtime Upgrade
With the new Wasm blob compiled, we can perform the on-chain runtime upgrade.
- Navigate to Polkadot-JS Apps for your parachain and go to Developer > Sudo.
- Select the
system
pallet and thesetCode
extrinsic. - Upload the new, compressed Wasm blob and submit the sudo transaction.
ℹ️ Wasm File Location: The required file is located at
target/release/wbuild/generic-runtime-template/generic_runtime_template.compact.compressed.wasm
.
After the transaction is finalized, the on-chain spec_version
will increase to 2. The block time will remain at 12 seconds because the running client is still the old binary, which does not have the async backing client-side logic.

Phase 4: Migrate the Client Node
The final step is to replace the running "old binary" with the "new binary" that understands the upgraded runtime logic.
This client-side migration is orchestrated using a Zombienet test script. The script programmatically stops the old node, updates its launch command to point to the new binary, and restarts it to complete the upgrade to a 6-second block time.