Laravel Chores is a package by Amr Lotfy Saleh for long, one-off data operations such as backfills and cleanups. It processes records in batches and writes the last processed ID to a chore_runs table after each batch, so a deploy, crash, or Ctrl+C loses at most one batch of work. Re-running the same command resumes where the run stopped. The design follows Shopify's maintenance_tasks gem for Rails.

A chore is a class with two methods: collection() returns the query for the records to touch, and process() handles one record. php artisan make:chore scaffolds the class. The batch size defaults to 500 via the config file unless set on the class. Batching, progress tracking, and failure logging happen around the class.

Batches use keyset pagination by primary key instead of offsets. That avoids the classic bug where updating rows shifts them out of the chunk being iterated. Records that throw are logged with their exception to a failures table and skipped, and the run continues. php artisan chore:failures inspects the failures and php artisan chore:retry reprocesses them after a fix, which is far cheaper than rerunning the whole job.

Six Artisan commands cover scaffolding, running, listing, pausing, inspecting failures, and retrying. chore:run shows live progress in the terminal; chore:pause stops at the next batch boundary. A JSON output mode plus distinct exit codes (0 clean, 1 completed with failures, 2 fatal) make the package CI-friendly. For recurring work, the command composes with Laravel's task scheduler, for example a monthly PurgeExpiredRecords run.

One caveat: checkpoints are per batch, not per record, so records inside an in-flight batch can be re-examined after a resume. process() should be idempotent where possible. Chores run in the foreground with a single worker per chore, and the collection needs an orderable primary key such as an auto-increment or ULID. Queued execution and parallel workers are on the roadmap; the Queue-SQL package already covers mass updates across queue workers.

The package requires PHP 8.2+ and Laravel 12 or 13, and supports MySQL, PostgreSQL, and SQLite. Installation runs composer require amrlotfy/laravel-chores, publishes the migrations, and migrates. Config options cover the chore class directory (app/Chores by default), default batch size, table names, and a sleep interval between batches for throttling. Source and documentation live on the AmrLotfy/laravel-chores GitHub repository.