Deploying and upgrading canisters
During deployment, there are two main concerns: canisters and code. The concern of canisters is all about where the code will end up running, and how to get it to the right place. The other concern is how code is managed to ensure there is no data loss, as little downtime as possible, and no misconfigurations. Since there are a lot of things to consider and many things that can go wrong during deployment, tools exist to make developers' lives easier. One such tool (which will be used as illustration on this page) is the IC Software Development Kit (SDK).
The Internet Computer runs arbitrary WebAssembly modules in so-called canisters. For the first deployment, new canisters have to be created for every individual WebAssembly module that is supposed to run. On creation of those canisters, they will be assigned a canister ID. Since there is no central registry of canisters, the developers (or more likely their tools) have to keep track of those IDs. Once code is deployed to canisters, the canister IDs can be used to call functions on other canisters.
Canisters consume cycles while they're running. Performing computation costs cycles, but so does storing data. As long as a canister is supposed to be running it has to contain enough cycles to maintain operations. This again is a place where developers (or their tools) need to keep track of IDs and/or cycles balances. If a canister runs very low on cycles, it will be frozen (meaning it won't respond to update calls anymore), and if it runs out entirely, it will be deleted.
Not everyone is allowed to change a canister. Canisters all have a list of controllers that are allowed to update its settings, install/upgrade the running code or even delete the canister. Developers, automated tools, other canisters or nothing at all can be controllers. Depending on the goals for the canister, different combinations of controllers can make sense. The below section demonstrating trust explains more about that.
Once a canister is at the end of its lifecycle, it can be deleted. Before doing so, it is recommended that (one of) its owner(s) withdraws remaining cycles before they delete the canister. Otherwise those cycles are lost. Since withdrawing those cylces is a rather tedious process manually, tools exist to facilitate the process. The other option besides deleting the canister is to just leave it running until it gets deleted automatically.
While canisters can run arbitrary WebAssembly (WASM) modules, the Internet Computer has a few conventions that make it easier to get the most out of its capabilities. For example, the function
canister_init is the first function that gets called after the code is installed for the first time. To facilitate adhering to those conventions, Canister Development Kits (CDKs) exist for many different languages.
To install code in a canister, the
install_code function of the Internet Computer is used in one of three modes:
installmode is the one every canister starts with: it is only callable for canisters without any installed code and populates the canister with the supplied WASM module. Once installation is complete, the aforementioned function
canister_init(usually exposed as
initin CDKs) is called if it exists. This allows the code to perform any required setup before any calls arrive.
reinstallmode works almost the same as
install, but if the canister already contains running code, its state is discarded and the running code is deleted. After that, the procedure from mode
upgrademode is the one used most often. This mode allows canister code to be changed without losing all of its state. In this mode, the canister first has the chance to save any state to stable memory in the
pre_upgradein CDKs) function. After that, the new code is installed and instead of calling the init function, the
canister_post_upgradefunction (exposed as
post_ugradein CDKs) is run so that data can be loaded from stable memory.
install_code modes are atomic. If anything goes wrong in one of the described steps, the canister state is reverted to its state before the
install_code function was called. And in case anything is not clear enough from these explanations, the IC specification for
install_code is the official source of truth.
Every function call on the Internet Computer has a limit to how many instructions can be executed. If your
pre_upgrade function exceeds this limit, it will be canceled and the upgrade fails. This can make a canister un-upgradeable. The Wiki contains some ideas how one can work around the cycles limit.
When upgrading existing canisters, there are a few more things that one should keep in mind:
- Outstanding callbacks: if a canister is
awaiting a response from another canister, it can be upgraded in-between sending and receiving a response. If the code is installed in
upgrademode, the callback will be executed as if no upgrade has been made. If this should not happen, the canister should either first be stopped, or the code has to be uninstalled and then installed again.
- Interface compatibility: if canisters or scripts expect the upgraded canister to have a certain interface, upgrades can break existing workflows.
dfxwill warn the user (if possible) that the upgrade will break certain signatures, but there are always corner cases that may be missed.
Things to consider
Internet Computer canisters are funded using a balance of cycles that will gradually burn down over time. You will be paying for the amount of memory you have allocated, as well as the CPU time that queries and updates take up.
Here is a checklist of the things you will need to consider:
- What will the canister's source of funds be?
- Paid for up-front by the developer.
- Funded by donations from the community.
- Funded by ongoing revenue in ICP or cycles.
- How will I monitor the canister's balance?
- What is your plan in case the balance runs low?
- What will happen if the balance runs out and the canister is eventually erased?
Depending on your use case, different answers will make sense for your application. Unlike other blockchains, where you assume that all content added is available forever, the Internet Computer requires you to think about the costs and sustainability of the computing resources that you are using.
An NFT project or DeFi canister may be able to self-fund by using transaction fees to purchase their own cycles. For other use cases, you may want a company or DAO to be responsible for supervising the balance. In any case, it is worthwhile to think about how you plan to ensure your canister's longevity.
A big topic in the blockchain space is how users can trust the smart contracts they interact with. Depending on the kind of project you want to deploy, different levels of trust can be appropriate.
Here is a checklist of the things you will need to consider:
- How much trust does this project require?
- How can I demonstrate that the canisters do what they are supposed to do?
- The sections trust in canisters and reproducible builds contain information related to this topic.
- How can users trust that the code will not suddenly change?