Workflow: Upgrade an existing hApp from 0.6 to 0.7
For a hApp already running on Holochain 0.6. If you are on 0.5, do the 0.6 upgrade first.
Authoritative source: developer.holochain.org/resources/upgrade/upgrade-holochain-0.7. This workflow sequences it and adds what the example hApp in this repo hit in practice. Where the two disagree, the official guide wins.
Step 0 — Decide whether to go now
Three things make this more than a version bump:
- The action model was rewritten. Every integrity zome’s
validatecallback and every coordinator’ssignal_actionneeds porting. This is the bulk of the work. - tx5 and WebRTC are gone. Iroh over QUIC is the only transport.
- There is no data migration path. DNA hashes change even for identical DNAs, and the databases were renamed. Existing installs must clear their data.
That third point is the decision gate: every 0.7 network is a new network.
- No production users yet → pure code port, go.
- Users whose data matters → the port is the easy half. You also need a data strategy, and the developer experience for it is incomplete. Budget for it separately and consider whether a clean restart plus a user-facing export/import is cheaper. See
migration.md.
Checkpoint: you know whether you are porting code only, or code plus user data.
Step 1 — Branch and re-pin the toolchain
Expect nothing to compile at the end of this step. That is normal.
git checkout -b upgrade/holochain-0.7
flake.nix:
holonix.url = "github:holochain/holonix?ref=main-0.7"; # was main-0.6
packages = (with pkgs; [
nodejs_24 # was nodejs_22 (legacy-ok)
binaryen
perl # add if your Sweettest build fails looking for it
]);
Do not use bare main: it now tracks the 0.8 dev line.
nix flake update && git add flake.* && nix develop
holochain --version # expect 0.7.0
Root Cargo.toml:
[workspace.dependencies]
hdi = "=0.8.0"
hdk = "=0.7.0"
If you have a holochain dev-dependency for Sweettest, its features changed:
holochain = { version = "0.7.0", default-features = false, features = ["encryption", "wasmer-sys-cranelift"] }
# was: features = ["sqlite-encrypted", "wasmer_sys", "transport-iroh"] (legacy-ok)
package.json: @holochain/client to ^0.21.0, @holochain/hc-spin to ^0.700.0.
Then cargo update and npm install. Delete every sandbox and conductor data directory in the repo; 0.7 cannot read them and the failure is confusing rather than explicit.
Checkpoint: cargo check fails with real API errors, not dependency-resolution errors.
Step 2 — Port the integrity zomes
This is the bulk. Do integrity first; coordinator code depends on the types.
The fastest route is not hand-porting. Scaffold a throwaway app with the same entry and link types and copy its dispatcher across:
hc scaffold -t headless web-app throwaway "tmp"
cd throwaway
hc scaffold -t headless dna d
hc scaffold -t headless zome z --integrity dnas/d/zomes/integrity/ --coordinator dnas/d/zomes/coordinator/
hc scaffold -t headless entry-type my_entry --dna d --zome z_integrity \
--fields "title:String" --crud crud --reference-entry-hash false --no-ui
Note --zome takes the integrity package name (z_integrity), not the directory name.
The renames you are applying, in full, are in patterns.md. The short version:
FlatOp::StoreEntry→CreateEntry,StoreRecord→CreateRecord,RegisterUpdate→Update,RegisterDelete→Delete,RegisterAgentActivity→AgentActivity, and both link variants →FlatOp::Link(OpLink::…)EntryCreationAction→TypedAction<EntryCreationData>Create/Update/Delete/CreateLink/DeleteLink→…Datastructs, matched onaction.dataaction.author→action.author()- Link validation functions lose their base/target/tag arguments; read them off the action
Checkpoint: integrity crates compile.
Step 3 — Port the coordinator zomes
signal_actionmatches on&action.hashed.content.datawithActionData::variants.get_agent_activitytakes a fourthGetOptionsargument and returnsAgentActivityStatus.ChainFilteruses constructors:ChainFilter::take(chain_top, 10), notChainFilter::new(chain_top).take(10).Record::newtakes aRecordEntry, not anOption<Entry>.block_agentandunblock_agentare removed, host functions included. WASM referencing them fails to instantiate. Application-level blocking built on them needs redesigning, not porting: blocking is now a system behaviour driven by warrants.must_get_agent_activityhas new response variants; match them if you match exhaustively.
Checkpoint: the workspace compiles.
RUSTFLAGS='--cfg getrandom_backend="custom"' \
cargo build --release --target wasm32-unknown-unknown
That RUSTFLAGS setting is required. Without it the build fails inside getrandom with a message about wasm32-unknown-unknown being unsupported, which does not look like a Holochain problem.
Step 4 — Conductor config and clients
Only if you maintain a conductor-config.yaml, for example in a Kangaroo build. NetworkConfig rejects unknown fields, so a leftover key is a startup failure, not a warning.
- Remove
signal_url,webrtc_config,chc_url - Move
request_timeout_sundernetwork db_sync_strategy→db_sync_level, valuesFull/Normal/Offwasm_backendis new and optional
JavaScript, see client.md:
SignedActionHashedis no longer genericaction.hashed.content.author→.header.authorTransportStats→ApiTransportStats,is_webrtc→is_directsignalingServerUrl→relayServerUrl
Step 5 — Tests
Sweettest is the supported path; hc scaffold no longer generates Tryorama.
await_consistencyhas a 60 second timeout;await_consistency_s(n, ..)for a custom oneConductor::install_app_with_manifestmoved behindtest_utilsmock_networkwas removed fromholochain_p2p- Inline zome definitions changed: closures moved to
DnaFile,InlineZome::uuidbecamehash
hc sandbox clean
cargo test
Step 6 — Packaging
Rebuild whatever you ship through and check its own 0.7 support first; conductor pins lag core. Kangaroo main-0.7 pins holochain 0.7.0.
Publish the new DNA hashes somewhere your users can see. The old network is not reachable from the new build.
Effort
| Step | Rough effort |
|---|---|
| 1 Re-pin toolchain | half a day |
| 2 Integrity zomes | two to four days |
| 3 Coordinator zomes | one to two days |
| 4 Config and clients | half a day |
| 5 Tests | one day |
| 6 Packaging | half a day, or open-ended |
Port the smallest hApp first to build the vocabulary, then the larger ones.