Work / Aakalan / Wiki / Concepts
recurring-is-a-rule
Conceptverified 2026-10-30
recurring-is-a-rule
A recurring expense is a RULE, not a queue. It produces a real expense on its due date and nothing before then. No greyed-out "upcoming" rows exist anywhere: an expense that has not happened must not move a balance, and one that looks like it might is how people stop trusting a shared ledger.
- Catch-up is explicit and one expense per occurrence, each dated to its own due date.
Two months away means two expenses, never one merged bill: that would be a number nobody
agreed, in the wrong month's insights. Capped at
MAX_CATCH_UPso an old device cannot materialise years of rent on one launch. - Never silent. Every generated expense carries an activity entry naming the rule, and Activity shows what was just added with an Undo. See a-record-is-never-erased.
- A rule whose group changed underneath it stops and says so. It never re-divides the
bill among whoever is there now.
isRuleStrandedderives this from the group on every read rather than storing it, so a member who leaves and returns fixes the rule by itself. - Rules live at
/users/{uid}/recurringeven when their expense belongs to a group: a rule is a private arrangement with yourself. Unlike an expense, a rule may be deleted outright: it is a setting, not a record of something that happened. - Pro lapsing pauses rules rather than quietly not running them, and the screen says
so.
RecurringRunnerholds the entitlement check, because the store has no business knowing about RevenueCat. src/lib/recurrence.tstakesnowas an argument, which makes "the app was closed for two months" a test rather than a bug report. The 31st in February falls back to the 28th and returns to the 31st the month after. It does not roll into March, which is whatnew Date(y, 1, 31)does.
Related: recurring, pro-never-gates-the-core-loop