Deploy and manage
Overview
Once a canister's code has been written, it must be compiled into Wasm, installed into the canister itself, and then deployed to a network. The dfx deploy
command executes each of these tasks as part of the deployment process; however, dfx
commands also exist for running each step individually.
It is recommended to deploy canisters locally or to the temporary playground network to test canister functionality and make adjustments before considering the canister production-ready and deploying it to the mainnet. Deploying canisters locally and to the playground is free and does not cost cycles. Once a canister is deployed to the mainnet, it will consistently consume cycles and will need to be topped up periodically.
Start the local replica
To deploy your canister locally, first start the local replica. This simulates the mainnet environment with a single node for local development and testing.
dfx start
: Returns replica output in the terminal window. A new terminal window will need to be opened to continue running commands.dfx start --background
: Runs the processes in the background and allows you to continue running commands in the current terminal.
Deploy locally
Deploy the backend canister that you have written code for:
dfx deploy PROJECT_NAME_backend --network=local
The --network=local
flag here is redundant and shown for educational purposes. The local network is the default setting for dfx
commands; therefore, no flag is needed to target it.
This will deploy your project to the local replica. In the background, this command:
Creates the canister(s) specified in the command; if no canister name was specified, it will deploy all canisters listed in the
dfx.json
file.Compiles the code for each canister into a Wasm module.
Installs the Wasm module into each canister.
Deploys the canister(s) to the deployment endpoint of choice (local, playground, mainnet).
Output
Deployed canisters.
URLs:
Backend canister via Candid interface:
PROJECT_NAME_backend: http://127.0.0.1:4943/?canisterId=be2us-64aaa-aaaaa-qaabq-cai&id=bkyz2-fmaaa-aaaaa-qaaaq-cai
Your deployed canister will now be executing two timers and printing the output directly to the terminal window:
2024-11-15 19:32:48.584899 UTC: [Canister bkyz2-fmaaa-aaaaa-qaaaq-cai] Generated new random proposal number: 133039
2024-11-15 19:32:51.197894 UTC: [Canister bkyz2-fmaaa-aaaaa-qaaaq-cai] Proposal info obtained through HTTPS outcall: {"action":"ManageNeuron","action_nns_function":null,"deadline_timestamp_seconds":1726953359,"decided_timestamp_seconds":1726783698,"executed_timestamp_seconds":1726783698,"failed_timestamp_seconds":0,"failure_reason":null,"id":113165,"known_neurons_ballots":[{"id":"28","name":"Internet Computer Association","vote":0},{"id":"27","name":"DFINITY Foundation","vote":0},
...
You can interact with the canister's public methods either in your web browser through the Candid UI URL that was returned in the deployment output or using the command line. Candid is an interface description language used to interact with a canister's public methods.
Upgrades
Canisters can be upgraded, allowing the same canister ID to be retained for an application. Upgrades preserve the state of a canister while allowing you to change the code. However, canister upgrades clear the canister's Wasm memory. Any data not stored in stable memory will be removed.
In your backend canister source code file, make a change such as increasing the timer to 60 seconds rather than 30 seconds. Save the file.
Next, you must compile the updated canister code into a new Wasm module. dfx build
is used for compilation:
dfx build PROJECT_NAME_backend --network=local
Then, upgrade your canister to use the new Wasm module:
dfx canister install PROJECT_NAME_backend --network=local --mode upgrade
Output
Upgrading code for canister PROJECT_NAME_backend, with canister ID bkyz2-fmaaa-aaaaa-qaaaq-cai
Confirm that the change you made results in the expected functionality or behavior. Then, stop the canister:
dfx canister stop PROJECT_NAME_backend --network=local
Deploy to the mainnet
Now that the canister has been tested, you can deploy it to the mainnet. Deploying to the mainnet costs cycles.
Confirm that you are using the correct developer identity and that you have an available cycles balance:
dfx identity whoami
dfx cycles balance --network=ic
Then, deploy to the mainnet:
dfx deploy PROJECT_NAME_backend --network=ic
The canister's Candid UI URL that is now hosted on the mainnet will be returned:
Deployed canisters.
URLs:
Backend canister via Candid interface:
PROJECT_NAME_backend: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=y4oop-liaaa-aaaab-qacha-cai
When a canister is running on the mainnet, you will always need to pass the --network=ic
flag to interact with it.
Settings
After a canister is deployed to the mainnet, it will constantly be consuming resources and cycles. To view information about how many resources and cycles currently being used, along with other information, view the canister's settings:
dfx canister status PROJECT_NAME_backend --network=ic
Output
Canister status call result for PROJECT_NAME_backend.
Status: Running
Controllers: hoqq7-3eo6j-dee4s-aiabk-6rqxw-kwgyo-rhru7-bdgmk-k5ipv-chkhx-cqe mwylj-4aaaa-aaaak-aflyq-cai
Memory allocation: 0
Compute allocation: 0
Freezing threshold: 2_592_000
Idle cycles burned per day: 31_243_414
Memory Size: Nat(3057320)
Balance: 196_157_756_924 Cycles
Reserved: 0 Cycles
Reserved cycles limit: 5_000_000_000_000 Cycles
Wasm memory limit: 3_221_225_472 Bytes
Module hash: 0x46cb1e5494b8467a13d0b6a68156b044eb79ce1325aa4bd4a697e36c9b967129
Number of queries: 1_469
Instructions spent in queries: 429_285_142
Total query request payload size (bytes): 1_626_898
Total query response payload size (bytes): 1_161_862
Log visibility: controllers
Status: Indicates if the canister is currently running, stopped, or stopping.
Controllers: Developer identities that have permission to manage the canister.
Memory allocation: The amount of memory resources requested by the canister.
Compute allocation: The amount of compute resources requested by the canister.
Balance: The current cycles balance of the canister. By default, this is 3T cycles. This default balance can be changed by passing the
--with-cycles
flag to thedfx canister create
command. This amount must be more than 100B, as the 100B cycles creation fee will be deducted from the amount you specify in--with-cycles
.Freezing threshold: A length of time specified in seconds. It reflects the amount of time estimated until the canister runs out of cycles based on the number of idle cycles burned by the canister.
Idle cycles burned per day: A calculation of how many cycles the canister burns per day without considering ingress or egress messages. The number of idle cycles is estimated based on the canister's size and the current cost of storage on the network.
Reserved: A separate cycles balance set aside for resource payments.
Reserved cycles limit: The maximum amount of cycles that can be set as 'reserved'.
Wasm memory limit: The maximum size for a canister's Wasm memory. Learn more about resource limits.
Module hash: The hash of the installed Wasm module.
Number of queries: Amount of query calls made to the canister.
Instructions spent in queries: Amount of instructions used in queries.
Total query request payload size (bytes): Total size of query request payload.
Total query response payload size (bytes): Total size of query response payload.
Log visibility: Who can view the canister's logs.
Topping up
A canister will burn cycles even in an idle state to pay for the network storage it uses. Additional costs will be charged whenever the canister sends and receives messages, uses compute resources, or uses special features like HTTPS outcalls and threshold signatures.
Even static canisters will eventually need to have their cycles balance replenished; otherwise, the canister will be deleted. This is known as "topping up" the canister.
Anyone can top up a canister. You do not need to be a controller of the canister to send it cycles.
To top up a canister, replace AMOUNT with the number of cycles to top up the canister with (i.e., 3T
to send 3 trillion cycles):
dfx cycles top-up PROJECT_NAME_backend AMOUNT --network ic
To check that your top up was successful, check the balance of the canister with dfx canister status PROJECT_NAME_backend --network=ic
.
Cycles management tools
Manually monitoring canisters to determine when they are getting close to the freezing threshold can be time-consuming and complicated if you have a project with many canisters. Several community tools exist to make monitoring canisters easy. Some of them allow you to set automation rules to automatically top up canisters if their cycles balance dips below a certain amount, while others provide a one-time top up workflow. Some of these tools include:
CycleOps: A comprehensive canister monitoring tool that provides top up automation, a statistics dashboard, email alerts, and the ability to create teams for synchronized management of collaborative projects.
ICPTopup.com: A simplified version of CycleOps that allows you to top up several canisters (up to 50) at one time.
Freezing threshold
To prevent a canister from running out of cycles and being deleted, you can set what is known as a freezing threshold. This threshold is a duration of time set in seconds, indicating the minimum duration that the canister should exist without running out of cycles. Once a canister hits this threshold, it will not execute messages. It will only pay for the network resources it uses, such as compute allocation, memory usage, and storage allocation.
The default value of the freezing threshold is 2_592_000 (approximately 30 days). To change the freezing threshold, update the canister's settings with the command:
dfx canister update-settings PROJECT_NAME_backend --network=ic --freezing-threshold SECONDS
If you set a freezing threshold longer than 1.5 years, you will need to include an additional flag: --confirm-very-long-freezing-threshold
.
Logging
Canister logs can be used to gain insight into a canister's behavior and assist with debugging situations such as when a canister traps.
View your canister's logs:
dfx canister logs PROJECT_NAME_backend --network=ic
By default, canister logs are only visible to the canister's controllers, but they can be made public by updating the canister's settings:
dfx canister update-settings PROJECT_NAME_backend --network=ic --log-visibility public
Snapshots
Canister snapshots are used as a checkpoint that can be used to roll back your canister to a previous version in the event that the latest upgraded version becomes unresponsive or stops working as expected.
To create a canister snapshot, first stop your canister:
dfx canister stop PROJECT_NAME_backend --network=ic
Then, take a snapshot of the canister's current Wasm code and data.
dfx canister snapshot create PROJECT_NAME_backend --network=ic
Output
Created a new snapshot of canister PROJECT_NAME_backend. Snapshot ID: 0000000000000000800000000010000a0101
Currently, only one snapshot per canister can be saved. Taking another snapshot will overwrite the existing snapshot.
View details about this snapshot:
dfx canister snapshot list PROJECT_NAME_backend --network=ic
Output
0000000000000000800000000010000a0101: 2.39MiB, taken at 2024-09-16 19:40:23 UTC
Deleting a canister
Deleting a canister removes the canister identifier, code, and state. The canister's source code will still be stored in your local environment and can be deployed as a new canister at any time. A canister must be stopped before it can be deleted.
Any cycles remaining in the canister's balance will be returned to your developer identity.
dfx canister delete PROJECT_NAME_backend --network=ic
Stopping dfx
To stop dfx
, simply use the dfx stop
command.
For unresponsive dfx
processes that are not stopped by dfx stop
, you can use dfx killall
to forcibly end them.
Getting help
To view help information for dfx
, you can use the dfx help
command or view the dfx
reference documentation.
Next steps
- View the developer next steps.