We would like to announce the following change that is now available (see IC Dashboard) on all ICP mainnet subnets: canister memory allocation no longer limits canister memory usage.
So Far
If a canister does not have any memory allocation (its memory allocation is set to zero), then every growth of its memory usage (growing WASM/stable memory, taking/loading a canister snapshot, uploading a WASM chunk, and upgrading the canister WASM) is best-effort, i.e., it succeeds only if
- the subnet has enough available memory to not exceed the subnet memory capacity (currently 2TiB - see documentation for the current value of the limit);
- and the canister does not become frozen after growing its memory usage (see documentation for more details about canister freezing);
- and cycles for storage can be reserved if the subnet is approaching its memory capacity (i.e., if the total subnet memory usage is beyond the threshold of 750GiB - see documentation for more details about the storage cycles reservation mechanism).
A controller of a canister can set canister memory allocation (during canister creation or later via the endpoint update_settings of the management canister - see documentation on how to change canister settings) to guarantee that subsequent canister memory usage growth always succeeds. This means that the above constraints only apply when setting or increasing memory allocation, but they do not apply for actual canister memory usage growth as long as canister memory usage stays within the canister’s memory allocation. On the other hand, canister memory usage growth always fails if canister memory usage would exceed the canister’s memory allocation.
The Change
We lifted the constraint that canister memory usage must not exceed the canister’s memory allocation at any time. Now canister memory usage growth is guaranteed to succeed as long as canister memory usage stays within the canister’s memory allocation (just like before) and becomes best-effort (subject to the above constraints on subnet available memory, freezing threshold, and storage cycles reservation) when canister memory usage grows beyond the canister’s memory allocation (instead of always failing which was the case before).
Storage cost is now based on
- canister memory allocation if canister memory usage is below the canister’s memory allocation;
- canister memory usage if canister memory usage is beyond the canister’s memory allocation.
We also refer to the corresponding section in the developer documentation.
Example
A canister has memory allocation of 100GiB and memory usage of 96GiB.
The canister is charged for its memory allocation of 100GiB.
Growing stable memory by 2GiB is guaranteed to succeed and memory usage becomes 98GiB.
The canister is still charged for its memory allocation of 100GiB.
Growing stable memory by additional 6GiB only succeeds if
- there are at least 4GiB of memory still available in the subnet without exceeding the subnet memory capacity;
- the canister is not frozen when its storage cost is based on canister memory usage of 104GiB;
- cycles for storage can be reserved for the additional 4GiB of memory beyond memory allocation (if the total subnet memory usage is beyond the threshold of 750GiB - see documentation).
The canister is then charged for its actual memory usage of 104GiB.