amphp/pipeline
amphp/pipeline provides fiber-safe concurrent iterators and collection operators for AMPHP event-driven PHP apps. Consume asynchronous sets with foreach, yield from, or iterator_to_array across multiple fibers. Requires PHP 8.1+; install via composer require amphp/pipeline.
Architecture fit: conditional, narrow. amphp/pipeline is not a Laravel package; it is a low-level AMPHP concurrency library built on PHP fibers and the Revolt event loop. It fits Laravel only in isolated, I/O-bound, long-running contexts such as CLI commands, queue workers, or internal services that fan out to external APIs. It is a poor fit for typical Laravel HTTP controllers, Eloquent-heavy flows, or code that assumes synchronous request-per-process execution. ConcurrentIterator, Pipeline, and Queue provide real value for fiber-safe streaming and back-pressure, but only when the work inside pipeline operators actually yields.
Integration feasibility: technically easy, behaviorally hard. Installation is a simple Composer dependency on PHP 8.1+, MIT licensed, with no service provider or Laravel auto-discovery. The hard part is that most Laravel application code is blocking: Eloquent, PDO, file operations, sessions, and many SDKs will block the event loop and erase the concurrency benefit. Meaningful use requires async-capable clients, such as AMPHP’s HTTP client, and strict isolation from Laravel’s request/container/global state. The package’s 83 stars and 0 direct dependents signal limited direct-market evidence, even though AMPHP itself is an established ecosystem.
Technical risk: medium-high for this stack. Key risks are fiber/async complexity, event-loop conflicts with Laravel Octane/Swoole, blocking calls inside concurrent closures, back-pressure deadlocks, and incorrect Queue lifecycle handling. The README explicitly warns that a queue must be completed or the consumer suspends indefinitely, and DisposedException must be handled when consumers disappear. Recent patch releases fixed race conditions and disposal/back-pressure behavior, which is normal for async libraries but confirms edge-case sensitivity. Using unordered() also means results may arrive out of order, so order-sensitive business logic needs explicit design.
Key questions for the TPM:
Http::pool, queue workers, Bus::batch, or Laravel’s Concurrency facade?DisposedException, and queue completion be enforced?Stack fit. Use this package behind a dedicated service boundary, not directly in controllers or models. Best candidates are queue jobs or CLI commands that perform I/O-bound fan-out: calling multiple external APIs, streaming large remote datasets, aggregating results with bounded concurrency, or merging multiple async sources. Pipeline operators such as concurrent(), buffer(), merge(), take(), map(), filter(), and forEach() map well to these workloads. For HTTP-heavy Laravel use cases, first compare against Http::pool; for batch processing, compare against multiple queue workers and Bus::batch.
Migration path. There is no data migration and no Laravel package wiring. Add the dependency in a branch, prove the use case in a single isolated command or job, and keep the existing synchronous path behind a feature flag. Wrap the pipeline in an application-owned adapter interface so callers do not depend on AMPHP types. Run the old and new paths in parallel on non-production traffic, compare latency, memory, error rates, and external API rate-limit behavior, then roll out gradually. Removal should be as simple as deleting the adapter and dependency.
Compatibility. Confirm PHP 8.1+ and Laravel version compatibility, then audit Composer conflicts around revolt/event-loop, amphp/amp, ReactPHP, and Swoole. Avoid introducing this into Octane/Swoole request workers without an explicit compatibility test; event-loop ownership and blocking behavior are the main concerns. Pin amphp/pipeline and its event-loop dependencies, and test on the exact production runtime rather than only local CLI.
Sequencing.
Maintenance. The library surface is small and semver-versioned, but async PHP code is materially harder to maintain than conventional Laravel code. MIT licensing means no commercial SLA; support depends on the AMPHP community and internal expertise. Pin versions and review release notes carefully, especially around queue disposal, back-pressure, and race-condition fixes. The low direct-adoption signal means fewer public Laravel-specific examples and less community troubleshooting evidence.
Support. The team will need an internal owner for async patterns, code review standards, and runbooks. Laravel documentation will not cover this integration. Debugging will require understanding fiber suspension, event-loop blocking, and pipeline cancellation. Without that owner, incidents will be slow to diagnose and likely to be “fixed” by removing concurrency.
Scaling. This package provides in-process concurrency, not horizontal scalability. It helps only I/O-bound work; CPU-bound work will not improve and may worsen due to event-loop overhead. Concurrency must be bounded with concurrent(n) and buffering controlled with buffer() to avoid memory growth and external API rate-limit failures. Horizontal scaling still belongs to queue workers, Horizon, and infrastructure autoscaling.
Failure modes to plan for. Missing Queue::complete() or error() can leave consumers suspended indefinitely. Blocking calls inside pipeline closures can stall the event loop. Unhandled exceptions in concurrent closures can fail the pipeline unpredictably. DisposedException must be handled when consumers stop early. Back-pressure can deadlock if producers and consumers are incorrectly coupled. Memory can grow if buffering is unbounded. Octane/Swoole event-loop conflicts can produce hard-to-reproduce runtime failures. These risks require explicit timeouts, cancellation, metrics, and load tests.
Ramp-up. Expect meaningful ramp-up: fibers, Revolt, async cancellation, and back-pressure are not standard Laravel skills. Budget for training, paired implementation, a reusable test harness, and observability before production use. As a TPM, I would not approve this as a platform-wide dependency; I would approve only a time-boxed, isolated PoC with a clear benchmark, an internal async owner, and a defined rollback path.
How can I help you explore Laravel packages today?