barracudanetworks/archivestream-php
Architecture fit. barracudanetworks/archivestream-php is a pure-PHP archive streaming primitive — it reads and writes ZIP and TAR byte-by-byte against a stream handle rather than materializing the archive in memory or on disk. That makes it a natural fit for a Laravel service layer that has outgrown ext-zip + temp files: bulk exports, on-the-fly bundles of objects pulled from S3-compatible disks, and iterating uploaded archives without extracting them. Critically, it is a library, not a framework plugin — no service provider, no config, no facade. It should therefore sit behind a contract we own (ArchiveWriter/ArchiveReader interfaces bound to a small Laravel service provider) so controllers and jobs never import vendor classes directly. That single decision is the difference between a reusable capability and a dependency we cannot swap.
Integration feasibility. Composer-installable, roughly a day of spike work to prove out both surfaces: (1) the write path, streaming a ZIP/TAR into Storage::writeStream() or a StreamedResponse; (2) the read path, enumerating entries in an uploaded archive without touching disk. PSR-7 stream interoperability means it composes cleanly with Flysystem-backed disks and guzzlehttp/psr7.
Technical risk. Four items dominate:
NOASSERTION) — not a recognized SPDX identifier in the package metadata. This is a gating item for legal/compliance and must be resolved before any code is written, not after.Key questions. What formats and compression do we actually need (ZIP-only would let us use the actively maintained maennchen/zipstream-php instead)? What is the p95 and max archive size/entry count in the export we intend to replace? Has legal cleared the license file? Is the read path exposed to user-uploaded archives? Which PHP minor are we targeting, and does the package's PSR-7 constraint resolve against Laravel's?
Stack fit. Framework-agnostic and Laravel-version-agnostic — it does not constrain Laravel 10/11/12. It fits the idiomatic Laravel seams: Storage/Flysystem streams, StreamedResponse, queued jobs, S3 disks. One architectural note: browser-facing streaming of a large bundle is CPU-bound inside PHP-FPM; for anything beyond a few hundred MB, prefer a queued job writing to object storage plus a signed URL over a long-lived streamed response.
Migration path. Nothing to migrate from, so adopt incrementally behind the interface. Where ext-zip + temp files exist today, the stream writer removes the file cleanup obligations and the disk-headroom class of incidents. Keep ext-zip as the fallback implementation of the same contract so a swap or rollback is a container binding change, not a code change.
Compatibility. The real gotcha is dependency resolution: a 2020-era package may pin psr/http-message ^1.0, which can conflict with modern Laravel stacks pulling PSR-7 v2. Confirm with composer why-not before estimating. PHP 8.2/8.3 will likely work but emit deprecations (implicit nullable parameters, dynamic properties) — budget a pass with E_ALL and decide whether to patch a fork.
Sequencing.
composer audit, license scanner) — stop/go.Maintenance. Effectively a vendored dependency with zero expected upstream activity. Decide early: pin-and-monitor or fork-and-own. A fork published to private Satis/Packagist gives us the ability to patch PHP 8 deprecations and, if needed, add ZIP64. Budget roughly 2–4 engineer-days per year and register it on the at-risk dependency list alongside any other orphaned libraries.
Support. No vendor SLA; community issues only, and low traffic at 77 stars. Named internal ownership is mandatory — an unowned archive path that silently corrupts exports is a quiet, high-blast-radius failure.
Scaling. The value proposition holds: constant memory, O(chunk) rather than O(archive). The cost moves to CPU — userland Deflate will be materially slower than libzip, so benchmark throughput per core before sizing workers, and expect to scale horizontally via queue consumers rather than vertically. Operational ceilings to document: 4 GiB / 65,535 entries without ZIP64, max_execution_time, load-balancer idle timeouts on long streams, and mandatory proxy buffering off for streamed responses.
Failure modes. The dangerous one is mid-stream failure: once headers are sent, a thrown exception yields a truncated archive with no way to signal an error — the client sees a 200 and a corrupt file. Mitigate by validating everything (entry existence, names, size budget) before the first byte, and by emitting a manifest or trailing marker consumers can verify. Secondary risks: S3/network 5xx mid-stream (same truncation class), zip-bomb on the read path, and FPM worker exhaustion from long-lived streams.
Ramp-up. Low. The API surface is small — one reader and one writer class per format — and a mid-level engineer is productive within a day. The learning curve is stream semantics and pre-flight validation discipline, not the library itself.
Verdict. Worth adopting narrowly, behind an owned interface, for streamed TAR/ZIP where memory or temp-file constraints are real — contingent on license clearance and a PHP 8 / PSR-7 resolution check. If the requirement turns out to be ZIP-write only, the maintained alternative is the lower-risk call and this evaluation should be closed.
How can I help you explore Laravel packages today?