Research · ICP
Canisters: actors, WebAssembly and memory
Last reviewed 2026-09-21Source: ICP Developer Docs — Canisters and the Internet Computer interface specificationArchitecture description only. No performance figure is quoted, because throughput depends on subnet load and canister configuration.
The actor model
The Internet Computer's execution model is built on actors. An actor is a computational entity that owns private state, communicates only by asynchronous message passing, and processes one message at a time. A canister is that actor given a home on the network: it has a principal that identifies it, a controller set that may upgrade it, and a cycles balance that pays for everything it does.
The single-threaded message loop is the property that matters most. Because a canister handles one message to completion before starting the next, its code never races against itself. There is no lock to take and no shared-memory concurrency to reason about. The cost is that a canister cannot block: an inter-canister call suspends the current message and returns control to the scheduler, and the reply arrives later as a new message. Code that assumes a call returns before the next line runs will be wrong.
This is a deliberate contrast with Bitcoin's model. A Bitcoin script is a predicate evaluated once to decide whether an output may be spent; it holds no state between evaluations and cannot call anything. A canister holds state, serves requests and calls other canisters, which makes it closer to a server process than to a script. The Bitcoin and ICP architecture comparison works through that difference in more detail.
WebAssembly modules
A canister's code is a WebAssembly module. The network does not execute source in Motoko or Rust; both compile to Wasm, and the replica runs the compiled module. That choice is what lets the platform support more than one language without changing the execution environment, and it is why the interface a canister exposes is defined in Candid rather than in a language-specific format.
The module exports entry points the runtime calls: update methods that go through consensus, query methods that are answered by a single replica, and system hooks such as canister_pre_upgrade and canister_post_upgrade. The interface specification defines the upgrade sequence precisely: the old instance's pre-upgrade hook runs, the new module is instantiated with fresh WebAssembly memory, and the post-upgrade hook runs on the new instance. Stable memory survives the whole process; ordinary WebAssembly memory does not.
The distinction between update and query calls is a design decision with visible consequences. An update call is replicated across the subnet and finalised through consensus, so its effects are durable and its result is agreed by the network. A query call skips consensus and is answered by one replica, which makes it fast and cheap but means the response carries weaker authenticity guarantees unless the canister certifies it. The decentralized frontends page explains how certification closes that gap for web assets.
The memory model
A canister has two kinds of memory, and the difference between them is the difference between surviving an upgrade and not. Ordinary WebAssembly memory is the heap the module allocates at runtime; it is discarded when the module is replaced. Stable memory is a separate address space that persists across upgrades, and it is where a canister keeps anything it cannot afford to lose.
Motoko takes a different approach from Rust here. Motoko's orthogonal persistence means a variable declared stable is retained automatically across upgrades, with no explicit serialisation step; the compiler enforces that stable variables have stable types. Rust has no equivalent, so a Rust canister must move its state into stable structures explicitly. The Motoko and Rust comparison sets out the trade-offs, and the upgrades and stable memory page covers the migration patterns that follow from it.
Memory is not free and it is not unbounded. Storage is charged per byte per second against the canister's cycles balance, and a canister whose balance falls below its freezing threshold stops processing update calls. That billing model is the subject of the reverse-gas model page.
Sources and references
The actor model, the WebAssembly execution environment and the memory model are described from the Internet Computer's own documentation and interface specification. No capability is asserted that the cited source does not describe.
- Canisters and the actor model. ICP Developer Docs, Canisters: describes a canister as a WebAssembly module with private state, a cycles balance and a principal.
- The upgrade sequence and stable memory. Internet Computer, Canister interface (system API): specifies the pre-upgrade and post-upgrade hooks, the fresh WebAssembly state, and the preservation of stable memory.
- Update calls, query calls and finality. ICP Developer Docs, Network overview: describes subnets finalising blocks roughly every second and query calls being answered by a single node.
Related reading
- Research HubEvery dataset on the site, with methodology and provenance.
- Altcoin ResearchAltcoins measured against Bitcoin: design intent, consensus, execution, scaling and market structure.
- The ETH-BTC Correlation RecordHow the correlation is measured, how it behaves across windows, and where it breaks down.
- The ETH/BTC RatioWhat the ratio measures, how to read its trend, and why it is not a forecast.
- ETH During Bitcoin Bull PhasesAssociation within a common market factor, and what co-movement cannot establish.
- ETH During Bitcoin Bear PhasesDrawdown depth and duration compared over identical windows, and the limits of the comparison.