KoriaVault

Nothing ticks

The obvious way to make a resource accumulate is a job that runs every minute and adds to everybody’s total. It is also the way that stops working the first time the process restarts.

Three numbers instead

stock      how much there was
stock_at   when that was true
rate       how fast it changes

Current stock is stock + rate × (now − stock_at), evaluated when somebody asks. Nothing runs in between. A colony nobody has looked at for three weeks costs exactly nothing to keep accumulating, and produces the correct answer the instant it is read.

A write happens only when the rate changes — a structure finished, a Reactor came on, a shortfall started or ended. At that moment you settle the old segment into stock, stamp stock_at, and store the new rate. The history of a colony is a series of straight lines, and the database only ever holds the last one.

Why this matters more than it sounds

It cannot drift. A ticking job that misses six minutes because the host was busy has lost six minutes of production, and there is no way to notice. Arithmetic against the wall clock has nothing to miss.

It cannot be double-counted. Two ticks firing at once is a duplicated payout. There are no ticks.

It survives a restart. The process going down for a deploy is not an event the economy is aware of. This matters here specifically: the game is one Node process on shared hosting, and it restarts whenever it feels like it.

It scales with players who are present, not players who exist. Ten thousand dormant colonies cost nothing. A ticking design charges you for every account that ever registered, forever, which is the wrong shape of bill.

The one thing it makes harder

Anything with a ceiling. A Depot cap means production is linear until the moment it is full and flat afterwards, so the closed form has a corner in it and you have to solve for when the corner happens rather than just multiplying. That is a few lines of arithmetic, and it is a much smaller problem than a scheduler.

The same reasoning is why build queues store a completion instant rather than a remaining duration. A duration has to be decremented by somebody; an instant is just true.