Welcome to the new Golem Cloud Docs! 👋
Documentation
Rust Language Guide
Updating Workers

Updating workers to newer versions of Rust components

As described in the general Workers page, each worker runs on a specific version of the component it is based on, but it is possible to update a worker to a different version of the same component.

Automatic update

The automatic update mode has no Rust-specific details and works as it is described in the general Workers page.

Manual snapshot-based update

Sometimes the change between two component versions is so large that the only solution to migrate worker's state to a new version is to manually implement this state transfer.

This is done by implementing a save-snapshot function in the old component and a load-snapshot function in the new component. The snapshot is an array of bytes and it is the responsibility of the user to ensure that the snapshot is compatible between the two versions.

These functions are defined in the golem:api WIT package and must be explicitly exported from the component's world.

Implementing the save snapshot function

The save-snapshot function must be explicitly exported from the component's world in it's WIT file:

package golem:demo;
 
interface api {
  // ...
}
 
world update-test-v3 {
  export golem:api/save-snapshot@1.1.0;
 
  export api;
}

This requires manually adding all the WIT dependencies Golem provides to the component's wit/deps subdirectory, and importing some of them in the Cargo.toml file.

Step 1: copy all the WIT dependencies

First copy the whole contents of https://github.com/golemcloud/golem-wit/tree/main/wit/deps (opens in a new tab) to the component's wit/deps directory.

Step 2: add the relevant dependencies to the Cargo.toml

Add the following dependencies to the Cargo.toml file:

[package.metadata.component.target.dependencies]
"golem:api" = { path = "wit/deps/golem" }
"golem:rpc" = { path = "wit/deps/wasm-rpc" }
"wasi:clocks" = { path = "wit/deps/clocks" }
"wasi:io" = { path = "wit/deps/io" }
"wasi:http" = { path = "wit/deps/http" }
"wasi:random" = { path = "wit/deps/random" }
"wasi:cli" = { path = "wit/deps/cli" }
"wasi:filesystem" = { path = "wit/deps/filesystem" }
"wasi:sockets" = { path = "wit/deps/sockets" }

Step 3: export the save-snapshot function

Add the following line to the component's world in its main WIT file:

export golem:api/save-snapshot@1.1.0;

Step 4: implement the save-snapshot function in Rust

An example implementation that just writes out an empty array of bytes:

struct Component;
 
use crate::bindings::exports::golem::api::save_snapshot;
 
impl save_snapshot::Guest for Component {
    fn save() -> Vec<u8> {
        let mut result = Vec::new();
        // ...
        result
    }
}

Implementing the load snapshot function

Implementing the load-snapshot function in the new component requires the same prerequisites as the save-snapshot function.

Once the WIT dependencies are set up, export the load-snapshot function in the following way:

export golem:api/load-snapshot@1.1.0;

and then implement it in Rust:

use crate::bindings::exports::golem::api::{load_snapshot};
 
struct Component;
 
impl load_snapshot::Guest for Component {
    fn load(_bytes: Vec<u8>) -> Result<(), String> {
        Err("Invalid snapshot".to_string())
    }
}

Note that the load-snapshot function can fail, indicating that it cannot load a previously saved snapshot. When the upgrade logic detects this, it reverts the worker to the previous version.

If the snapshot can be loaded, the load-snapshot function must set up the worker's global state and return with Ok(()).