All Docs
FeaturesagentOS Direct DebitUpdated March 13, 2026

Collection Scheduling & BACS Submission Job

Collection Scheduling & BACS Submission Job

Available from: v1.0.27

The collection scheduling job is the automated engine that drives rent collection. It runs on a daily schedule, determines which mandates are due within the upcoming BACS submission window, and submits collection requests to Modulr on their behalf.


How It Works

1. Daily Cron Trigger

The job is implemented as an Inngest cron job that fires once per day. On each run it:

  1. Queries all active mandates to find those whose next collection date falls within the current BACS submission window
  2. For each due mandate, submits a collection request to Modulr
  3. Records the outcome as a collection record with status submitted

2. Collection Records

Every successful submission creates a collection record in the database. The initial status is always submitted. Status transitions (e.g. to collected, failed, or clawback) are handled by subsequent jobs as Modulr webhooks arrive.

3. Idempotency & Duplicate Prevention

Each submission is keyed by a deterministic idempotency key derived from the mandate ID and the collection date. If the cron job runs more than once in a day (e.g. due to a retry or re-deployment), duplicate Modulr submissions are automatically rejected and no duplicate collection record is created.


Edge Cases

Day-of-Month Overflow

Some mandates are configured to collect on a day that does not exist in every month — for example, the 31st, or the 29th–31st of February. When this occurs, the job adjusts the collection date to the last working day of the current month rather than skipping the collection entirely.

Mandate Collection DayMonthResolved Collection Date
31stApril (30 days)Last working day of April
31stFebruaryLast working day of February
29thFebruary (non-leap year)Last working day of February

Suspended Mandates

Mandates with a status of suspended are excluded from the submission run. No collection request is sent to Modulr and no collection record is created for that cycle. Collections resume automatically once the mandate is reactivated.

Duplicate Submission Guard

In addition to idempotency keys on the Modulr API call, the job checks whether a collection record already exists for the mandate and target collection date before submitting. This two-layer guard prevents double-collections regardless of whether the duplicate originates from the cron scheduler or from a manual re-trigger.


Collection Lifecycle (after submission)

Once a collection is in submitted status, the rest of the lifecycle is event-driven:

submitted → collected → swept to Griffin holding → held → forwarded to client account
                ↓
             failed / clawback

See the Fund Flow documentation for details on sweep, hold, and forwarding behaviour.


Configuration

The BACS submission window and working day calendar are governed by service-level configuration. The job respects UK bank holidays when calculating effective collection dates — mandates due on a bank holiday are moved to the next available working day.