Upgrades
An actor in Motoko is written in a source file (often called main.mo
). The Motoko code is compiled into a Wasm module that is installed in a canister on the Internet Computer. The canister provides main memory for the actor to operate on and store its memory state.
If we want to incrementally develop and evolve a Web3 Service, we need to be able to upgrade our actor code.
New actor code results in a new Wasm module that is different from the older module that is running inside the canister. We need to replace the old module with the new one containing our upgraded actor.
Immutable Microservice
Some actors, may stay unchanged after their first installment in a canister. Small actors with one simple task are sometimes called microservices (that may be optionally immutable and not owned by anyone). A microservice consumes little resources (memory and cycles) and could operate for a long time without any upgrades.
Reinstall and upgrade
There are two ways to update the Wasm module of an actor running in a canister.
Reinstall
When we have an actor Wasm module running in a canister, we could always reinstall that same actor module or a new actor module inside the same canister. Reinstalling always causes the actor to be 'reset'. Whether reinstalling the same actor Wasm module or a new one, the operation is the same as if installing for the first time.
Reinstalling always wipes out the main memory of the canister and erases the state of the actor
Upgrade
We could also choose to upgrade the Wasm module of an actor. Then:
- The actor interface is checked for backwards compatibility
- The pre-upgrade system function is run before the upgrade
- The canister Wasm module is upgraded
- Stable variables are restored
- The post upgrade system function is run after the upgrade
NOTE
Pre and post upgrade hooks could trap and lead to loss of canister data and thus are not considered best practice.
Service upgrades and sub-typing
When upgrading a service, we may also upgrade the public interface. This means that our actor type and public interface description may change.
An older client that is not aware of the change may still use the old interface. This can cause problems if for instance a client calls a function that no longer exists in the interface. This is called a breaking change, because it 'breaks' the older clients.
To avoid breaking changes, we could extend the functionality of a service by using sub-typing. This preserves the old interface rather than the memory state and is called backwards compatibility. This will be discussed later in this book.
Upgrading and reinstalling in Motoko Playground and SDK
When we have an already running canister in Motoko Playground and we click deploy
again, we are presented with the option to upgrade
or reinstall
(among other options).
The same functionality is provided when using the SDK.