Product Decisions This Supports
- Build vs. buy for background CLI orchestration. The bundle lets a Symfony app enqueue console commands and drain them through a worker, so product teams can ship "run this long task later" features (bulk imports, report generation, cache warmups, data syncs, PDF/export jobs) without inventing a job table, a dispatcher, and a supervisor loop from scratch. That is typically 1–3 engineer-weeks of undifferentiated plumbing.
- Sequential-by-design workloads. Many product features are not throughput-bound but correctness-bound: they must not run two at a time, must not overtake each other, or must respect a downstream rate limit. A command queue that processes one job at a time is the right primitive for "nightly reconciliation runs after the previous one finishes," and it removes a class of incidents caused by overlapping cron entries.
- Replacing brittle cron sprawl. If the roadmap includes scheduled operational jobs, this package is a candidate to consolidate N crontab lines into one managed worker — a roadmap-level maintainability decision, not just a technical one.
- Feature gating and tiering. A queue is a natural place to attach priority and throughput policy, which supports packaging decisions: "standard" tenants get one worker, "enterprise" gets a dedicated queue and higher concurrency. The package gives you the seam for that without a bespoke scheduler.
- Operational surface for support. Because jobs are persisted and inspectable, support can answer "did the export actually run, and when?" — a product-visible capability (status pages, admin retry buttons) that raw
exec() calls in a controller can never provide.
- Not a fit for Laravel. Laravel already ships queues, Horizon, and
Bus::batch(); adopting this bundle there would duplicate core framework capability with a third-party dependency. Treat it as Symfony-only scope.
When to Consider This Package
Adopt when most of the following hold:
- The application is Symfony (this is a bundle, not a framework-agnostic library) and you want a queue that speaks the language of "run this
bin/console command," not "dispatch this serialized message object."
- Workloads are moderate volume, high duration: tens to low thousands of jobs per day, each taking seconds to minutes. The value is offloading wall-clock time from the request cycle, not achieving high throughput.
- You need strict ordering or mutual exclusion — no overlapping runs, FIFO per queue — and you would otherwise be reaching for
flock and cron.
- The team is small and wants a narrow dependency: MIT-licensed, small surface area, readable source. The realistic exit strategy is "vendor it into
src/" or fork it, which is cheap here.
- You are early in a service's life and the alternative is Symfony Messenger plus a transport (Doctrine, Redis, AMQP), a supervisor config, retry/DLQ policy, and worker deploy tooling. That is a heavier commitment than many teams need at this stage.
Look elsewhere when any of the following is true:
- You are on Laravel. Native queues, batching, chaining, rate limiting, and Horizon monitoring already cover this. There is no decision to make.
- You need a real message bus. Fan-out, competing consumers, per-job retries with exponential backoff, dead-letter queues, delayed/scheduled dispatch with fine granularity, idempotency keys, cross-language producers — Symfony Messenger, RabbitMQ, or SQS. This bundle is a command runner, not a broker.
- You need observability as a product feature. No metrics, tracing, or dashboard story here; you will be building that yourself against the persistence layer.
- Supply-chain risk is unacceptable. Ten stars and zero dependents means no community backstop. If your org requires SOC2-style dependency review or a maintenance SLA, this fails regardless of code quality. Only proceed if you are prepared to own the code.
- You need horizontal scale-out. Multiple workers across hosts, lease/heartbeat semantics, and stuck-job recovery are the hard parts of queues, and a low-star bundle is unlikely to have battle-tested them.
How to Pitch It (Stakeholders)
To executives (one paragraph): We have a recurring, low-glamour engineering cost: long-running background tasks — imports, exports, reports, syncs — currently handled with cron entries and ad-hoc scripts that overlap, fail silently, and generate support tickets. This package is a small, MIT-licensed Symfony component that queues those console commands and runs them one at a time under a single supervised worker. The business case is not new revenue; it is reliability and time-to-ship. It removes a class of "the export ran twice / never ran" incidents and lets us add background features without re-plumbing each time. The cost is low and the exit cost is near zero — the code is small enough to fork. The honest caveat: it is a single-maintainer project with negligible adoption, so we budget a small amount of engineering to own it rather than assume the community will.
To engineering (the real pitch): Stop writing exec() in controllers and stacking crontab lines. This gives us a persisted command queue with a single worker, ordering guarantees, and no overlapping execution — the 80% case for operational jobs in a Symfony app. It is not Symfony Messenger and we should not pretend it is: no retries-with-backoff, no DLQ, no transport abstraction, no metrics. Adopt it deliberately as an internal, vendored dependency with a thin wrapper interface (enqueue(Command): JobId, status(JobId)) so that if we outgrow it, we swap the implementation for Messenger behind the same seam. Evaluate this quarter against a two-day spike of doing it ourselves; if the spike wins, we keep the interface and drop the dependency.
Decision requested: Approve a short evaluation spike and a "vendor-or-fork" maintenance stance, not a long-term platform commitment.