Scheduled Tasks
Every task Signals runs on a schedule, how often it runs, and how to run the scheduler and queue workers.
Last reviewed against source:
Run the scheduler
Signals registers all of its recurring work with the Laravel scheduler in routes/console.php. The scheduler does nothing until something calls it every minute. On a self-hosted server, add one cron entry for the user that owns the application:
* * * * * cd /path/to/app && php artisan schedule:run >> /dev/null 2>&1
Check it with php artisan schedule:list, which shows each entry and its next due time.
The first scheduled entry writes a heartbeat to the cache every minute. Admin → System → System Health reads that heartbeat: the Scheduler card is green when it is no more than five minutes old, and warns when it is older or missing. php artisan doctor --only=signals-scheduler runs the same check from the command line. See System Health.
All times below are UTC. Entries marked "one server" take a cache lock so that only one server runs them in a cluster; use a shared cache such as Redis when you run more than one application server. Entries that do not overlap skip a run while the previous one is still going.
Run the queue workers
Many scheduled entries dispatch queued jobs rather than doing the work themselves, and so do web requests. A scheduler without workers queues jobs that never run.
- During development,
composer run devstarts a queue listener alongside the web server. - In production, run
php artisan queue:workunder a process manager such as Supervisor or systemd, and restart it after every deployment withphp artisan queue:restart. - A worker started without
--queuehandles only thedefaultqueue. Signals dispatches jobs to these named queues, so name them all:default,availability,approvals,embeddings,exports,imports,notifications,privacy,webhooksandworkflows. For example:php artisan queue:work --queue=default,availability,approvals,embeddings,exports,imports,notifications,privacy,webhooks,workflows. - Set
QUEUE_CONNECTIONtoredisorsqsfor production. Without it, the queue connection falls back todatabase. See Installation.
The Queue card on System Health shows whether named queues are draining and lists failed jobs, which a user with settings.manage can retry.
Every minute
| Task | What it does |
|---|---|
| Scheduler heartbeat | Records the time of the last run so System Health can tell the scheduler is alive. |
signals:base-currency-identity:backfill |
Backfills base-currency identity on historical records and refreshes open rentals. One server; skips overlap. |
| Reverse due currency revaluations | Reverses currency revaluations that have fallen due. |
signals:dispatch-scheduled-workflows |
Dispatches due runs of published scheduled workflows. |
signals:billing-runs:dispatch-pending |
Recovers billing-run attempts left between claim and queueing. |
signals:billing-runs:dispatch-issue-effects |
Recovers pending billing-run PDF, communication and dashboard effects. |
signals:credits:dispatch-issue-effects |
Recovers credit-note issue effects without resending uncertain email. |
signals:finance:dispatch-customer-effects |
Recovers standalone invoice and payment customer notifications. |
The four finance entries run as --apply with a per-run limit.
Every five minutes
| Task | What it does |
|---|---|
signals:dispatch-report-schedules |
Queues delivery for every report schedule that is due. |
signals:api:flush-logs |
Flushes buffered API metering entries into persistent storage. |
| Retry due privacy cases | Retries approved or failed account privacy cases that are due. |
| Drain account mutation effects | Completes pending follow-up work after account changes. |
| Drain rental attachment effects | Completes pending follow-up work after rental attachment changes. |
| Drain webhook outbox | Hands pending webhook deliveries to the queue, catching any that were missed. |
| Expire approval requests | Expires pending approval requests that are past their deadline. |
| Escalate approval assignments | Escalates approval assignments that have waited too long. |
| Expire approval delegations | Expires approval delegations that have ended. |
| Expire credit reservations | Expires credit reservations that are past their expiry time. |
Every fifteen minutes
| Task | What it does |
|---|---|
signals:billing-runs:reconcile-attempts |
Inspects stale billing-run claims and settles items that have receipts. |
signals:workflow-timing:repair |
Repairs delayed workflow timing operations. |
Hourly
| Task | What it does |
|---|---|
signals:api:warm-doc-caches |
Warms the API specification and documentation caches in the background. |
signals:plugin-cache |
Compiles the enabled plugin list and manifests to the plugin cache. |
signals:finance:integrity |
Reports read-only invoice and billing-run integrity findings, at 20 minutes past the hour. |
signals:accounts:health --alerts |
Reports account identity, merge, credit, privacy and search integrity alerts. |
| Evaluate account retention | Evaluates account retention and opens review cases where needed. |
| Expire put-asides | Releases expired put-aside holds. The put-aside demand source is not built, so this currently does nothing. |
| Expire waitlist monitors | Expires stale shortage waitlist monitors. |
signals:shortages:escalate-unresolved |
Notifies when shortages on confirmed orders approach dispatch unresolved. |
signals:virtual-stock:detect-overruns |
Notifies when virtual stock intakes pass their available-until date without return. |
signals:expire-scan-sessions |
Abandons stale open scan sessions. |
Overdue checks
Two entries share a cadence set by the Overdue check interval (minutes) setting under Admin → Preferences → Scheduling, described in Scheduling settings. The default is 60, which is hourly. Values below 60 run every that many minutes, whole hours run every that many hours, and other values round up to a whole hour. The setting accepts 1 to 1440 minutes.
| Task | What it does |
|---|---|
signals:availability:detect-overdue-demands |
Extends overdue, unreturned demands so availability keeps reflecting stock that has not come back. |
signals:rentals:detect-late-returns |
Notifies when orders still have equipment out past their end date. |
Daily
| Time | Task | What it does |
|---|---|---|
| 00:00 | signals:api:prune-logs |
Prunes API request and inbound webhook logs past retention. |
| 00:00 | queue:prune-failed --hours=720 |
Removes failed-job records older than 30 days. |
| 00:00 | model:prune |
Runs Laravel's pruning for models that opt in. |
| 00:00 | Prune availability data | Removes availability snapshots, summaries and events beyond their retention settings. |
| 00:00 | signals:scan-equipment-tests |
Recomputes equipment test due dates for all assets. |
| 00:00 | signals:scan-flightcase-overruns |
Notifies when flightcase contents overrun their sub-hire return deadline. |
| 01:00 | signals:exchange-rates:fetch |
Fetches exchange rates for enabled currencies from an automatic provider. One server. |
| 01:30 | Sync changed embeddings | Embeds new and changed records for AI search. |
| 02:00 | signals:action-log:prune |
Prunes action log entries past retention. |
| 02:10 | signals:ai-usage:prune |
Prunes AI usage log entries past retention. |
| 02:15 | signals:embeddings:prune |
Removes expired embeddings and those whose source no longer exists. |
| 02:30 | signals:communication-log:prune |
Prunes the communication log past retention. |
| 02:35 | signals:workflow-evidence:prune |
Prunes workflow evidence details and keeps redacted summaries. |
| 02:40 | signals:webhook-outbox:prune |
Prunes settled webhook outbox entries past retention. |
| 02:50 | signals:tenant-magic-nonces:prune |
Prunes consumed magic-link nonces. |
| 03:00 | signals:recently-viewed:prune |
Keeps only the newest recently viewed items per user. |
| 03:15 | signals:recent-searches:prune |
Prunes recent searches past retention. |
| 03:15 | signals:imports:prune-staging |
Prunes import staging files for completed, cancelled and abandoned imports. |
| 03:30 | Refresh account quality recommendations | Recomputes data-quality recommendations for accounts. |
| 03:30 | Verify snapshot integrity | Samples availability snapshots, repairs any drift and logs it. |
| 03:30 | signals:exports:prune |
Deletes expired export files. |
| 03:40 | signals:accounts:health |
Runs the full account health report without alerts. |
| 03:40 | signals:reports:prune-delivery-files |
Deletes scheduled report delivery files whose email did not succeed, after 24 hours. |
| 03:45 | Prune account privacy artifacts | Removes expired or revoked privacy case artifacts. |
| 04:00 | signals:accounts:revalidate-expired-vat |
Queues VAT number revalidation for accounts whose cached check has expired. |
| 04:15 | Roll up utilisation | Rolls up the day's utilisation figures for reports. |
| 04:30 | Roll up asset valuations | Rolls up asset valuations for reports. |
| 06:00 | signals:invoices:process-overdue |
Dispatches overdue side effects for unpaid invoices past their due date. Skips overlap. |
| 07:00 | signals:rentals:detect-expiring-quotes |
Notifies when quotes approach their expiry date. |
| 08:00 | Digest notifications | Sends each user one summary email of unread notifications that they opted into digests for. |
Weekly or monthly
| Task | When | What it does |
|---|---|---|
| Refresh all embeddings | Sundays at 02:15, or the 1st of the month at 02:15 | Re-embeds every record for AI search. The ai.refresh_cadence setting chooses weekly (the default) or monthly. |
Signals Cloud
On Signals Cloud one scheduler serves every tenant, so each entry above runs once per active tenant and failures in one tenant do not stop the others. The Cloud schedule also runs migrate --force --isolated every five minutes and prunes failed jobs centrally. Cloud queue workers are managed for you.
Related
| Reference | Use it for |
|---|---|
| System Health | Scheduler and queue checks |
| Scheduling settings | The overdue check interval |
| Installation | Queue and cache drivers |
| Backup and Restore | Protecting the data these tasks maintain |