Cycle burn rate heartbeat

It definitely takes some work, but the proportions just seem off.

0.5 TC a day works out to almost $0.70 per day, which is roughly $21 per month or $252 per year.

That means heartbeat (a simple version) is 50x more expensive than storing 1 GB of data for a year on the IC.

I definitely agree that a public heartbeat canister that anyone can subscribe to and whose cycle costs are split among its subscribers would be very useful, but I don’t think the community will be able to organize around such a service in the near future…


Yeah also thought of this, but issue is that my implementation is for a self-scaling storage solution, so for example;
there is a storage canister, once it reaches a certain memory threshold it locks up for any further update calls and spins up a “brother” canister. So eventually the update calls will stop once the canister is full.

I think the only way your solution would work is to make every query call an update call, or can a query call internally call an update call? :thinking:

so eventually the update calls will stop once the canister is full.

Ah, I see.

or can a query call internally call an update call?

No, it can’t do any inter-canister call.

Since inter-canister update calls take awhile, I wonder if there’s a hacky solution in here where you can set up a canister to recursively call other canisters, and only repeat the inter-canister call once the calling canister has received a response (2+ sec).

This “heartbeat” wouldn’t be as predictable in terms of timing, but would most likely be less expensive.

haha this sound like worth trying, but my assumption is that it would be pretty expensive.

If i understand you correctly it would be something like

--storage canister--
fn get_cycles() {

--storage management canister--
fn request_cycles() {
   storage_canister_get_cycles().await // based on caller

And then maybe work with some kind of delay solution

Yes, or even self-calls although that is less safe - IC Cron - let's schedule some tasks bois - #3 by nomeata

1 Like

It’s way cheaper to do this instead of using heartbeat. I moved to running a script on a server that calls an upgrade method on my canister every 2 seconds because of costs. It would be nice if we could reduce heartbeat costs to make it as cheap as calling the canister from the “outside”.


I have this hacky system I’m my ICDevs bounty roadmap. A dao that owns this “scheduler” public utility would be a fun project.

Maybe I’ll code it up for supernova.

Interesting problem and needed data:

How many fire and forget intercanister calls can fit into one round of consensus?

Do we need guaranteed delivery? Rouge canisters probably break in line processing of returns….would need to use @nomeata ’s upgrade pattern.

How do the economic play out? How much for 10,000 notifications, etc.

It’s sounds like what you really want is a hook into when a canister reaches the freezing threshold so that you can provide a method that will get called where you could top up the cycles.

Do you have any numbers, e.g. average cost per call? At a 2s interval, it could be 1/2 of the cost, since heartbeat runs roughly every 1s.

Or help us implament - Bounty #17 - A DAO for Cycles - $10,000 - ht: cycle_dao

Yeah if there was a way to trigger a function once the canister doenst have enough cycles to process the call, that would be a great addition

That is exactly what does. It will maintain a canister’s cycle balance to the average of last 10 days, and refill as needed.

1 Like

I wish there was an analogous inspect_message for heartbeats, where a canister can choose to accept or reject a heartbeat call and not pay any cycles if it chooses to reject it… I don’t think this exists though.


Honestly I think a way to create custom heartbeats should be provided by default by the ICP, its a feature needed for many use cases and in my opinion we shouldn’t rely on a 3rd party service that has to be trusted and somehow funded to do something so basic.


That is exactly the spirit of open services. Why shun away from it?

1 Like

Because in my opinion having to pay to use a basic feature like custom heartbeats is just stupid, the fact its not offered by the “framework” by default and we as a community have to gather and discuss how and who will implement it even more, it looks really bad from an outside perspective. Like imagine if you were introduce a friend of your to ICP:
-“Hey how can I define a custom heartbeat?”
-“Well you can’t, the community has been discussing it but still no ETA and you’ll have to pay for it, if you don’t want to wait you can do it yourself and spend lot of cycles everyday”

Most would laugh, I welcome the nature of web3 but we should be building new stuff not a web3 version of setTimeout.


What’s the difference between that and any other feature of the IC? You pay to compute. It costs X cycles to store a value in stable64 memory, it costs Y cycles to call the management canister, it costs Z cycles to call the (community provided) cron canister. Computation as a service is the entire model.

I’m not saying that a custom-length heartbeat would be bad - there is a line between stuff the IC should provide and stuff it shouldn’t, and I’m not sure which side I think this falls on - but scheduled execution and consensus every second for potentially every canister on a subnet does have a computational cost, and the cycle cost is meant to represent that.

The difference is you pay cycles for what you actually use be it computation or storage, if I want to run a function once every 24 hours and I have to pay for useless calls every second, that is stupid. If it were a very niche use case then I’d agree with you, but this is something lots of dApps need. I want to use the IC to build new stuff not reinvent the wheel.

1 Like

So who’s gonna pay for keeping track of the schedules?