Lock every money-moving sweep, and run two pods

FeatureBillingService
Shipped
September 4, 2026 at 9:01 PM UTC
Author
Kamo
Commit
02d70b3

BillingService ran one pod and its seven scheduled sweeps were correct only because of it. There is no ShedLock anywhere on this platform, so a second replica would have run each of them twice a tick: **************** submits metered usage to the payment provider — submitted twice, the customer is charged twice DunningSweep retries failed payments AND emails about them StorageAutoExpandSweep buys storage on the customer's behalf, and bills it TrialExpirySweep ends trials and moves subscriptions on MailboxBillingReconciler / PbxBillingReconciler fight over the same subscription items StorageSnapshotSweep double-counts every org's nightly usage figure Each now takes a named lease through SingletonTaskRunner before doing anything. StorageSnapshotSweep is the one exception in shape: its sweep() is ALSO called straight from StorageUsageController when an operator asks for a snapshot now, and returns the row count for the response. So the @Scheduled annotation moved to a new scheduledSweep() that takes the lease, and sweep() itself is untouched and still directly callable — an operator's explicit request should not be silently skipped because another pod happens to be mid-sweep. replicas 1 -> 2.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing