Skip to content

docs: canister lifecycle guide#28

Merged
marc0olo merged 4 commits into
mainfrom
docs/guides-canister-management-lifecycle
Mar 19, 2026
Merged

docs: canister lifecycle guide#28
marc0olo merged 4 commits into
mainfrom
docs/guides-canister-management-lifecycle

Conversation

@marc0olo
Copy link
Copy Markdown
Member

@marc0olo marc0olo commented Mar 19, 2026

Summary

  • Complete canister lifecycle guide: create, build, install, deploy, upgrade, stop/start, reinstall, delete
  • Covers icp deploy's auto stop/restart behavior during upgrades (icp-cli v0.2.1+)
  • Motoko persistent actors and Rust stable structures for state preservation
  • Subnet migration: motivation, two approaches (snapshot transfer vs full migration), when to preserve canister ID, link to icp-cli guide
  • Programmatic canister management (factory pattern) in both Motoko and Rust
  • Canister history, trapping/error handling, and Wasm size limits
  • All code verified against .sources/ (cdk-rs, motoko, motoko-core, examples, icp-cli)

Sync recommendation

informed by dfinity/portal — docs/building-apps/canister-management/, docs/building-apps/developing-canisters/ + dfinity/icp-cli — docs/concepts/build-deploy-sync.md, docs/guides/canister-migration.md

Cover the full canister lifecycle: creation, building, installation,
deployment, canister states, upgrades with state persistence (Motoko
persistent actors and Rust stable structures), reinstallation, deletion,
programmatic canister management via the management canister, canister
history, trapping/error handling, and Wasm size limits.

All code snippets verified against .sources/ (motoko, cdk-rs, examples).
All CLI commands verified against icp-cli docs/reference/cli.md.
@marc0olo
Copy link
Copy Markdown
Member Author

Review

Must fix

  1. Motoko HashMap does not exist in mo:core (line 183): The Cache example uses HashMap.HashMap<Text, Text>(16, Text.equal, Text.hash), but mo:core has no HashMap module. The old mo:base library had HashMap, but mo:core (which is the required library per project conventions) uses Map instead. The snippet needs to be rewritten using Map.empty<Text, Text>() from mo:core/Map, or use a simpler illustration (e.g., a plain var array or list) since the point is demonstrating transient keyword behavior, not hash maps.

  2. Content brief gap: subnet migration not covered: The stub's content brief explicitly lists "migration between subnets" as a topic to cover. The page only mentions migration once in passing (line 101, in the states table). The source material references Portal: advanced/canister-migration.mdx and icp-cli: guides/canister-migration.md. At minimum, the page should include a brief section (or a paragraph with a cross-link) noting that icp canister migrate-id enables moving canisters between subnets, with a reference to the icp-cli guide for details. This is a documented icp-cli command (icp canister migrate-id exists in the CLI reference).

  3. Unverifiable claim about icp deploy not restarting stopped canisters (line 125): The page states "Note that icp deploy does not restart a manually stopped canister -- you must explicitly start it." I could not find confirmation of this behavior in .sources/icp-cli/docs/concepts/build-deploy-sync.md or the CLI reference. This should either be verified against the icp-cli source code or flagged with <!-- Needs human verification: does icp deploy skip stopped canisters? -->.

Suggestions

  1. Motoko factory code drops caller from controllers (lines 274-298): The page's simplified Motoko factory sets controllers = ?[Principal.fromActor(Factory)], meaning only the factory is a controller. The upstream example at .sources/examples/motoko/canister_factory/src/backend/Main.mo (line 232) includes both caller and the factory actor as controllers: controllers = ?[caller, Principal.fromActor(Main)]. For a docs guide, omitting the caller from controllers could mislead developers into creating canisters they can't control directly. Consider making the function shared({caller}) and including the caller.

  2. "Remaining cycles are refunded to the caller's cycles balance" (line 264) is imprecise: The portal source (.sources/portal/docs/building-apps/canister-management/delete.mdx) says cycles are returned "to the cycles wallet or cycles ledger account associated with the canister's controller principal. If the canister has multiple controllers, then the principal that made the delete request receives the cycles." Consider being more specific.

  3. Canister history section could mention the 20-change limit more precisely (line 329): The page says "most recent 20 changes" which matches the IC spec, but it would be helpful to clarify that this is the minimum guaranteed — the IC always retains at least the 20 most recent changes, though older changes may be dropped.

  4. Missing import in Cache example (lines 180-185): The Cache example uses HashMap.HashMap but doesn't show the import statement. Even after fixing the HashMapMap issue, showing the import helps readers copy-paste correctly.

  5. Consider adding a note about --mode upgrade being implicit in icp deploy: Lines 132-133 show both icp deploy my-canister and icp deploy my-canister --mode upgrade. It would help to note that --mode upgrade is rarely needed explicitly since auto mode (the default) already does the right thing. The explicit flag is primarily useful for CI pipelines that want to fail if the canister doesn't already exist.

Verified correct

  • All 9 internal links resolve
  • All CLI commands and flags match .sources/icp-cli/docs/reference/cli.md
  • Install modes table (auto, install, upgrade, reinstall) matches CLI reference
  • Rust canister_info code matches .sources/examples/rust/canister-info/src/lib.rs
  • Rust create_canister code matches CDK API in .sources/cdk-rs/
  • Rust pre_upgrade/post_upgrade hooks verified against .sources/cdk-rs/ic-cdk/src/storage.rs
  • Motoko persistent actor, transient, and (with cycles) syntax verified against .sources/motoko/doc/md/16-language-manual.md
  • Motoko factory code structure matches .sources/examples/motoko/canister_factory/
  • 10 MiB Wasm module size limit confirmed
  • Canister ID non-reuse after deletion confirmed
  • No dfx references, no banned links
  • Frontmatter complete, build passes

- Fix HashMap → Map.empty() in transient Cache example (mo:core has no HashMap)
- Add subnet migration section with icp canister migrate-id
- Remove incorrect claim about icp deploy not restarting stopped canisters
  (v0.2.1 now stops before upgrade and restarts after)
- Add caller to factory controllers (matches upstream example)
- Clarify cycles refund goes to the controller who made the delete request
- Clarify canister history retains at least 20 most recent changes
- Document that --mode upgrade is rarely needed (auto handles it)
- Add stop/restart steps to upgrade sequence
@marc0olo
Copy link
Copy Markdown
Member Author

Feedback addressed:

  • HashMap → Map: Replaced HashMap.HashMap with Map.empty() from mo:core/Map in the transient Cache example, with proper import
  • Subnet migration: Added new section covering icp canister migrate-id with link to icp-cli guide
  • icp deploy + stopped canisters: Removed incorrect claim. Updated upgrade sequence to document that icp-cli v0.2.1 stops before upgrade and restarts after
  • Factory controllers: Added shared({caller}) and included caller in controllers list (matches upstream example)
  • Cycles refund: Clarified that cycles go to the controller who made the delete request
  • Canister history: Clarified 20-change limit is a minimum guarantee
  • --mode upgrade note: Added note that auto mode handles this; explicit flag is mainly for CI

Explain why migration is needed, the two approaches (snapshot transfer
vs full migration), and when preserving the canister ID matters. Link
to the comprehensive icp-cli migration guide for procedures.
The check-upstream-notes workflow expects <!-- Upstream: ... -->,
not <!-- Sync recommendation: ... -->.
@marc0olo marc0olo merged commit ffe42ba into main Mar 19, 2026
1 check passed
@marc0olo marc0olo deleted the docs/guides-canister-management-lifecycle branch March 19, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant