Getting Started with IC Development: What considerations should developers take into account when developing a canister locally and deploying it to the IC Mainnet

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:

  1. Stop canister
  2. Take snapshot
  3. Upgrade canister
  4. 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.

4 Likes

Thanks for sharing and driving this effort! :slight_smile:

The subnet limit is 1TB :grin: and the canister storage limit is 500GB. See the Stellarator milestone.

3 Likes

I believe there’s a typo here: the subnet limit is 1TB.

1 Like

of course!:man_facepalming: fixed :white_check_mark:

funny if that happens when trying to correct somebody else :rofl:

1 Like

In my article, I specifically noted that it’s Stable Memory that has a 500 GB limit, not canister storage. In practice, Stable Memory often better reflects a canister’s true storage capacity—because in large-data scenarios, most developers rely on stable structures to store their data.

A particularly interesting development is the evolution and application of wasm64 within canisters, which could become a new storage paradigm.

In any case, thank you for pointing that out! :grin: