Build, Deploy, Sync
Canisters go through three distinct phases when moving from source code to running on the Internet Computer.
Overview
Source Code → [Build] → WASM → [Deploy] → Running Canister → [Sync] → Configured StateEach phase has a specific purpose:
| Phase | Purpose | Commands |
|---|---|---|
| Build | Compile source to WASM | icp build or icp deploy |
| Deploy | Create canister and install WASM | icp deploy |
| Sync | Post-deployment configuration | icp deploy or icp sync |
Note: icp deploy runs all three phases in sequence. Use individual commands when you need more control.
Build Phase
The build phase transforms your source code into WebAssembly (WASM) bytecode.
What Happens
- Build steps from your configuration execute in sequence
- Each step can run commands, copy files, or process assets
- The final output is a
.wasmfile ready for deployment
Key Points
- icp-cli delegates compilation to your language toolchain (Cargo for rust, mops for Motoko, etc.)
- Build output should be reproducible — no environment specific values should be baked in.
- The toolchain decides whether rebuilding is necessary.
- As part of the build phase you might build assets to be synchronized to the canister after the was is installed. For example, bundled web assets to serve a frontend.
Build Step Types
Script — Run shell commands:
build: steps: - type: script commands: - cargo build --target wasm32-unknown-unknown --release - cp target/wasm32-unknown-unknown/release/my_canister.wasm "$ICP_WASM_OUTPUT_PATH"Pre-built — Use existing WASM:
build: steps: - type: pre-built path: dist/canister.wasm sha256: abc123... # Optional integrity checkAssets — Bundle static files:
build: steps: - type: script commands: - npm run buildEnvironment Variables
Scripts have access to:
ICP_WASM_OUTPUT_PATH— Where to place the final WASMICP_PROJECT_ROOT— The project root directory
Deploy Phase
The deploy phase creates or updates canisters on a network.
First Deployment
When deploying a canister for the first time:
- An empty canister is created on the network
- The canister receives a unique canister ID
- Initial cycles are allocated
- Canister settings are applied (memory, compute allocation, etc.)
- Your WASM code is installed
Subsequent Deployments
When the canister already exists:
- The existing canister is located by ID
- New WASM code is upgraded (preserving stable memory)
- Settings are updated if changed
Sync Phase
The sync phase handles post-deployment operations that depend on the canister being deployed.
Common Use Cases
- Asset canisters — Upload static files after the canister is running
Asset Sync
For frontend canisters, sync uploads your built assets:
sync: steps: - type: assets dir: distWhen Sync Runs
- Automatically after
icp deploy - Manually with
icp sync
Run sync without redeploying:
icp sync my-canisterThe Full Picture
What icp deploy Does
The icp deploy command is a composite command that executes multiple steps in sequence:
- Build — Compile all target canisters to WASM (always runs)
- Create — Create canisters on the network (only for canisters that don’t exist yet)
- Update Canister Environment Variables — Apply the updated Canister Environment Variables. These include variables used by bindings allowing canister interactions.
- Update Settings — Apply canister settings (controllers, memory allocation, compute allocation, etc.)
- Install — Install WASM code into canisters (always runs)
- Sync — Run post-deployment steps like asset uploads (only if sync steps are configured)
Initial vs Follow-up Deployments
First deployment:
- All steps run
- New canisters are created on the network
- Settings are applied
- WASM code is installed (install mode)
Subsequent deployments:
- Skip the canister creation
- Settings and Environment Variables are applied if they’ve changed.
- WASM code is upgraded, preserving canister state
Unlike icp canister create (which prints “already exists” and exits), icp deploy silently skips creation for existing canisters and continues with the remaining steps.
Install Modes
The --mode flag controls how WASM is installed:
# Auto (default) — install for new canisters, upgrade for existingicp deploy
# Install — only works on empty canistersicp deploy --mode install
# Upgrade — preserves state, runs upgrade hooksicp deploy --mode upgrade
# Reinstall — clears all state (use with caution)icp deploy --mode reinstallEquivalent Individual Commands
What icp deploy does can be broken down into:
icp build # 1. Buildicp canister create # 2. Create (if needed)# (canister env vars updated) # 3. Set environment variables# (canister settings updated) # 4. Sync settingsicp canister install --mode auto # 5. Installicp sync # 6. Sync (if configured)Running Phases Separately
For more control, run phases individually:
# Build only — compile without deployingicp build
# Sync only — re-upload assets without rebuilding or reinstallingicp syncWhen to run separately:
icp build— Verify compilation succeeds before deployingicp sync— Update assets without redeploying code (faster iteration for frontends)
Note: icp deploy always builds first. There’s no way to skip the build phase during deploy. The build phase relies on the underlying toolchain (Cargo, moc, etc.) handling incremental compilation.
Next Steps
- Local Development — Apply this in practice