Background
This article, as the first in the Building a Community-Driven Knowledge Base for IC Development series, gathers all the metrics and details I’ve focused on during ICP canister development—from local development through deployment and maintenance in production.
Developers are welcome to further enrich this mind map; after thorough discussion on the forum, it will be consolidated into a dedicated GitHub repository.
I’ve contributed this content as a Markdown article, along with mind-map images attached to the post. I built the mind map using XMind—if you need the PDF version or the original XMind file, feel free to DM me to get them.
Local Development
CDK Version
- Use the latest Rust CDK version.
- Pay attention to CDK API interface changes when upgrading between versions.
- Check for known security issues of the target CDK version on the Dfinity forum.
Benefits of Developing on Localnet
- Local development doesn’t incur any fees—in other words, you don’t need to spend ICP/cycles.
- Immediate access to detailed operational logs and debugging through the console.
- On mainnet, retrieve logs using:
dfx canister --ic logs $canister_id
Important Development Constraints
- Be mindful of canister execution constraints: memory, compute limits, and execution cycles.
- Early consideration prevents later maintenance issues. Refer to IC documentation.
Canister Upgrade
- See the “Canister Maintenance” section for detailed upgrade guidance.
Canister Maintenance
Storage
WebAssembly (WASM) Memory
- Current WASM memory limit is 4GB, anticipated to extend to 6GB with wasm64 support.
- Data not requiring upgrades can reside fully in WASM memory.
- Reference: WASM64 Beta Announcement.
Stable Memory
- Stable memory is subnet-shared, totaling 500GB per subnet.
- Primarily used during upgrades via hooks like
pre_upgrade
, unless using stable structures. - Recommended to store large data sets using stable structures for easy upgrades and decoupling data from logic.
Canister Upgrade
- Ensure the
pre_upgrade
hook never fails to prevent permanent upgrade blockage. - Strongly recommend using stable structure libraries for managing stable memory.
Suggested Upgrade Workflow:
- Stop canister
- Take snapshot
- Upgrade canister
- Start canister
Snapshot
- Canisters retain up to 10 snapshots, allowing reversion in case of upgrade failures.
Cycles
Freezing Threshold
- Default freezing threshold: 30 days.
- Below this threshold, canisters reject update calls but allow query calls.
- Exhausted cycles lead to data loss; controller retains canister ID for 10 years.
Instruction Limitation
- Update and query calls have strict instruction limits.
- Exceeding limits results in state rollback. Always monitor instruction usage.
Canister Settings
- Optional compute and memory allocations reserve resources.
- Typically unnecessary unless subnet resources are constrained to guarantee QoS.
Deploying a Canister to Mainnet
Choosing a Subnet
Based on Node Count
- More nodes increase security and operational costs:
- 34-node subnet (~2.6x cost of 13-node subnet)
- 13-node subnet
Chain Key Signature Efficiency
- 13-node (
fuqsr
) and 34-node (pzp6e
) subnets directly support chain key signatures. - Other subnets delegate to these.
Subnet Load
- Busier subnets can increase execution latency.
- MIEPS: Higher indicates busier subnet.
- Finalization rate: Higher generally reduces latency.
Based on Region
- Europe (
bkfrj
): All nodes located in Europe. - Other regional subnets available.
Subnet Eligibility
- Subnets reaching maximum canister capacity reject new deployments.
- Check Dfinity forums for subnet availability.
Multi-Canister Architecture: Same or Different Subnets
Same Subnet
- Faster communication; max payload 10MB.
- Lower latency.
Different Subnets
- More overall stable memory.
- Load balancing capability.
- Reduced operational costs by distributing canisters based on security and latency sensitivity.