Skip to main content

Background jobs

Servicing runs as scheduled sweeps on the admin host's worker. Each is a Warp recurring job, fired on a cron by a distributed-locked scheduler — so it runs once per cluster, not once per instance. The partner host runs none of these; it only serves requests against the same database.

The schedule

JobCronWhat it does
Daily servicing02:00 dailyCharge → age → delinquency → late fees, as a chain of continuations (each step waits for the previous, so no step works on stale data).
Provisioning01:00 dailyRecomputes IFRS-9 provisions and posts the impairment.
GL postinghourlyPosts the sub-ledger to the double-entry general ledger, so the Accounting view trails the loan closely.
Disbursement dispatchevery 5 minDispatches pending Loanly payouts to the bank rail and retries failed ones (idempotent). See Disbursement.
Bank-claim reconciliationevery 15 minPulls settled bank-claim payments back and records them. No-ops unless the bank rail is configured.
Token cleanup03:00 dailyPrunes expired/consumed email tokens and revoked sessions.

The daily servicing chain

The 02:00 run is a single trigger that enqueues its steps as continuations rather than four independently-scheduled jobs:

charge due installments
└─▶ age installments
└─▶ delinquency buckets
└─▶ late fees

Chaining (vs. spacing jobs out on separate crons) guarantees each step sees the previous step's committed result — aging never runs before charging finishes, and so on. Each run is logged (start, outcome, duration) and every step is idempotent, so a retry or an overlapping trigger is safe.

Where they're registered

All schedules are registered once at startup (idempotent upsert, under a distributed lock, so it's safe on every instance). Registration is skipped in the Testing environment — tests drive the job handlers directly instead.