yokai/batch
Yokai Batch is a Laravel package for running and managing batch jobs, with tools to define batches, track progress, and handle failures in queued workloads. It integrates with Laravel's queue and provides a simple API for orchestrating long-running or bulk tasks.
Architecture fit. yokai/batch is a Spring Batch–inspired abstraction layer for PHP: Job → Step → (ItemReader / ItemProcessor / ItemWriter) or Tasklet, with a persisted JobRepository tracking JobExecution/StepExecution and execution context for restart-from-failure. The core is framework-agnostic and interface-driven; framework concerns (Doctrine, Symfony Serializer, League CSV, Symfony console/framework bundle) live in separate satellite packages in the monorepo. That decomposition is good news for Laravel: we can consume only yokai/batch (plus the CSV bridge if useful) and avoid dragging Symfony/Doctrine bridges into a Laravel dependency tree. Conceptually it fits the "nightly ETL / chunked import-export / restartable data pipeline" slot that Laravel's native Bus::batch() does not cover — Laravel batching is queue-job fan-out, not chunk-oriented read/process/write with skip and retry policies.
Integration feasibility. No first-party Laravel bridge exists (the only framework integration is yokai/batch-symfony-framework). The integration work is bounded and well-defined but non-trivial:
DB (including optimistic locking, since the interface assumes concurrent execution safety).batch:run {job}) plus a service provider binding readers/processors/writers into the container.Technical risk. The dominant risk is not technical, it's sustainability: 12 stars, 0 dependents, a single-maintainer org, and a last release of December 2023 (≈2 years stale at time of review). Adopting this is effectively adopting a codebase we may need to vendor and maintain ourselves. Secondary risks: unknown compatibility with current PHP (8.4) and Laravel 11/12; no observable community answer base; and API stability is unproven at this adoption level. The concept risk is low — the abstractions mirror a 20-year-old, well-understood pattern, so the mental model survives even if the library doesn't.
Key questions.
JobRepository contract stable and documented well enough to implement correctly against Eloquent, including locking semantics?composer.json permit PHP 8.3/8.4 and coexist with Laravel's pinned Symfony components (relevant only if we touch any bridge)?Bus::batch() for each pipeline we'd migrate?Stack fit. Good. Composer-only, PHP 8.1+, no C extensions, PSR-friendly interfaces, and a PHPStan extension in the monorepo (a positive quality signal). The Symfony/Doctrine satellites are optional and should be avoided — they are the most likely source of dependency-graph conflicts with Laravel's locked Symfony versions. Plan on: yokai/batch + yokai/batch-league-csv (if CSV I/O is needed) + our own Eloquent reader/writer and JobRepository adapters.
Migration path. Greenfield-first, strangler-fig later. Do not retrofit existing queued jobs. Pick a single non-critical, naturally chunked pipeline (nightly CSV import, catalog sync, report materialization) behind a feature flag, in an isolated module. If it proves out, expand pipeline-by-pipeline and only then consider replacing incumbent jobs.
Compatibility. Primary unknowns are PHP version ceiling and any transitive Symfony constraints. Mitigation: install the framework-agnostic core only, run composer why-not checks against the Laravel lock file, and pin exact versions. The PHPUnit bridge is useful — it implies jobs are unit-testable without a real data source, which shortens the feedback loop materially.
Sequencing.
batch:run Artisan command, Eloquent-backed JobRepository (with locking + indexed execution tables), container bindings for job definitions.Maintenance. Assume we own this. The surface is small and interface-heavy, which makes it cheap to maintain — but there is no upstream safety net, so budget roughly 0.1 FTE ongoing for the Laravel adapter plus occasional patches, and a defined policy for vendoring/forking under our org if the upstream stalls. Pin exact versions; do not float.
Support. No commercial support, minimal community, Symfony-flavored docs and examples. Internal ownership and internal documentation are mandatory. The compensating factor is that the pattern is standard enough that a competent engineer can reason about behavior without upstream help.
Scaling. Chunk-oriented processing gives bounded memory per worker — a genuine advantage over naive ->get() loops. Horizontal scale is ours to design: multiple workers over partitioned inputs, with the JobRepository as the coordination/contention point (needs proper indexing and correct optimistic locking). Restart-from-failure is the headline capability, and it works only if our repository implementation is correct.
Failure modes.
--max-time style guards.Ramp-up. Spring Batch concepts (chunk vs. tasklet, skip/retry policies, execution context) are unfamiliar to most Laravel developers, whose mental model is jobs-and-queues. Expect ~1–2 weeks for a senior engineer to be independently productive, plus documentation effort. Weigh this against the opportunity score: the package is genuinely useful only where you need restartable, chunk-oriented ETL with skip/retry semantics — for plain fan-out batch work, Laravel's Bus::batch() remains the lower-risk default, and this package should be scoped narrowly to the pipelines that actually need it.
How can I help you explore Laravel packages today?