Research · Cross-chain
ICP and Solana: canister-centric and program-centric design
The canister as a stateful actor
The Internet Computer's documentation describes a canister as a WebAssembly module with its own persistent memory, deployed to a subnet and replicated across that subnet's nodes. The canister has an address, a cycles balance and a controller, and it can expose update methods that mutate its state and query methods that read it. Because the memory persists across calls, a canister is closer to a long-running server process than to a function: it accumulates state, it can be called by users and by other canisters, and it can itself call out to other canisters or to external chains through threshold signatures.
The actor framing is not decoration. The documentation's programming model is explicitly an actor model: canisters communicate by asynchronous messages, an update call that calls another canister cannot return a value to its caller in the same round, and the developer composes behaviour out of messages rather than out of nested function calls. That is a real constraint, and it is the price of the isolation that lets each canister hold its own state and be upgraded independently.
Storage is part of the same picture. A canister's memory is charged for continuously, and the documentation describes a stable-memory mechanism that lets a canister keep data across upgrades without serialising it into the heap. The developer therefore makes an explicit decision about what lives in ordinary memory and what lives in stable memory, and that decision is what makes an in-place upgrade safe.
The Solana program as stateless code
Solana inverts the arrangement. The documentation describes a program as executable code that holds no state of its own, and an account as the container that holds data and a lamport balance. A program is invoked with a list of accounts, and it reads and writes those accounts; the state an application accumulates lives in accounts that the program owns or is granted authority over, not inside the program. The program is therefore closer to a pure function over accounts than to a server process.
That separation is what makes the parallel runtime possible. Because every instruction declares the accounts it will touch, the scheduler can run non-overlapping instructions concurrently, and because the program itself holds nothing, there is no per-program state that would have to be locked. The cost is that the developer designs the account layout as part of the program's interface: which accounts exist, who owns them, how their data is laid out and which instruction is allowed to write them are all decisions the program's correctness depends on.
Paying for storage follows from the same model. The documentation describes rent as a lamport balance an account must maintain to stay on chain, with the balance proportional to the space the account occupies. Storage is therefore paid for by whoever funds the account, and an account whose balance falls below the threshold can be purged. That is a different arrangement from a canister's cycles balance, but it answers the same question: who keeps this data alive, and what happens when they stop.
Upgrading an application, and what survives
On the Internet Computer, an upgrade replaces the canister's WebAssembly module while preserving its memory, and the documentation describes pre-upgrade and post-upgrade hooks that let the developer migrate state between layouts. The canister keeps its address and its cycles balance, so users and other canisters do not have to be redirected. The security boundary is the canister's controller list: whoever controls the canister can replace its code, and the platform enforces that rather than the application.
On Solana, a program's code is stored in an account, and the documentation describes a program account as upgradeable when it is marked as such and owned by the upgradeable loader, with an upgrade authority permitted to write a new program buffer into it. A program deployed as final is not upgradeable at all. Because the program holds no state, an upgrade does not have to preserve anything inside it: the accounts the program operates on are untouched, and the new code simply reads and writes them under whatever layout rules it expects. The migration problem moves entirely into the account layout, where a change in how data is encoded is the developer's responsibility.
The two arrangements therefore place the same risk in different spots. A canister upgrade risks the canister's own memory, which is why the hooks exist. A program upgrade risks the account layout, which is why the account schema is effectively part of the program's public interface. Neither platform removes the need to think about how old data meets new code.
The two application models side by side
The table states the structural differences between a canister and a Solana program. Each row is drawn from the platform's own documentation.
| Dimension | ICP canister | Solana program |
|---|---|---|
| Who owns the state | The canister itself, in its own memory | Accounts, which the program reads and writes |
| Where state lives | Canister memory, with stable memory for upgrade-safe data | Account data, laid out by the program's own schema |
| How storage is paid for | Cycles, charged continuously for memory and compute | Rent, a lamport balance proportional to account size |
| How the code changes | The module is replaced in place, with migration hooks | A new program buffer is written by the upgrade authority |
| What an upgrade risks | The canister's own memory layout | The account layout the new code expects |
| How programs interact | Asynchronous messages between canisters | Instructions that declare the accounts they touch |
| Who can change the code | The canister's controllers | The program's upgrade authority, or no one if final |
Last reviewed 2026-09-21Source: ICP and Solana developer documentationStructural comparison; no cost or performance figure is asserted.
What the comparison does not settle
The table describes where state lives, not which arrangement is better for a given application. A canister that holds its own state is convenient for a service that accumulates data and is upgraded by its operator; a stateless program over explicit accounts is convenient for a workload that needs to run in parallel and whose state is naturally partitioned. The right answer depends on the application, and the documentation of neither platform claims otherwise.
The comparison is also silent on the questions this cluster covers elsewhere. It does not describe how either network reaches finality, which is the subject of the finality comparison, and it does not describe how either one represents a transaction or grows its state, which the transaction and data model comparison takes up. Read together, the four pages describe the same two networks from four angles.
Finally, both platforms are under active development. The Internet Computer's canister model and Solana's runtime and account rules have both changed since their introductions, and this page describes them as their documentation describes them at the review date. Where a mechanism is proposed rather than deployed, the documentation says so, and this page does not present a proposal as a capability.
Sources and references
Each platform's application model is described from its own documentation. No capability or figure is asserted that the cited source does not state.
- Canisters, memory and upgrades. ICP Developer Docs, Canisters and code: a canister holds persistent memory and is upgraded in place, with pre- and post-upgrade hooks.
- The actor model and asynchronous calls. ICP Developer Docs, Actors and canisters: canisters communicate by asynchronous messages, and an update call cannot return a value in the same round.
- Solana's accounts and programs. Solana Docs, Accounts: programs are stateless, accounts hold data and lamports, and rent is a balance proportional to the space an account occupies.
- Upgradeable programs. Solana Docs, Programs: a program account is upgradeable when owned by the upgradeable loader, and an upgrade authority may write a new program buffer.
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.