Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Chunky Laravel Package

netipar/laravel-chunky

Resumable, chunk-based file uploads for Laravel. Send large files reliably over flaky connections with server-side chunk tracking and fingerprint-based resume. Typed backend plus Vue, React, Alpine and Livewire frontends. No queue worker or broadcasting required by default.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Chunky is architecturally opinionated in ways that suit a Laravel monolith or an Inertia/SPA hybrid rather than a distributed platform. The backend is a ports-and-adapters design (tracker contract with database and filesystem drivers, transport contract with standard and direct_s3), and the frontend is a single framework-agnostic engine with thin Vue 3 / React / Alpine / Livewire adapters. For us that means one upload subsystem to reason about across all our UI surfaces instead of per-framework reinventions. The genuinely valuable architectural property is the module-level manager on the client: uploads are owned outside the component tree, so SPA navigation does not cancel in-flight transfers. That is the single hardest thing to retrofit into an ad-hoc uploader, and it is the reason to consider adopting rather than building.

The second notable fit is the profile abstraction. Validation, disk, directory, authorization, filename, and the post-assembly completed() hook are colocated in one class. That maps cleanly onto our typical per-domain media workflows (avatars, documents, gallery assets) and gives us an auditable policy surface. The Chunky::simple() shortcut covers throwaway cases without a class. Worth noting the batch endpoint validates against the batch's profile, which closes an obvious privilege-escalation hole — a sign the author has thought about abuse, not just the happy path.

Integration feasibility. Low-friction on paper: composer require + php artisan chunky:install + migrate on the backend; a single configure({ baseUrl, headers }) call on the frontend; one service-provider registration per profile. The default auto assembly mode ships without a queue worker or broadcasting, which is the correct default for teams that do not want upload infrastructure as a prerequisite. Config is validated at boot into a typed ChunkyConfig and fails fast on a bad key — good for catching misconfiguration at deploy time rather than at 2 a.m. under load.

The friction points are real, though. The package targets PHP 8.3+ and Laravel 12/13 only. Any application on Laravel 10/11, or on PHP 8.2, is out unless we upgrade first. That is a hard gate and should be the first thing we verify across the estate. The frontend packages live under the @netipar npm scope, so we inherit a single-org supply-chain dependency for four packages; pinning and lockfile review are mandatory.

Technical risk. Ranked:

  • Adoption risk (highest). 0 stars, 0 dependents, no third-party production references. The README, docs (EN + HU), changelog, releases, SECURITY.md, and an OpenAPI spec are all present and the code is PHPStan-max / strict-TS — this reads as a competent, disciplined author, not a weekend script. But documentation quality is not evidence of operational durability. There is no track record of how it behaves under concurrent production load.
  • API churn. v1.0 is explicitly a ground-up rewrite from 0.x with an UPGRADE.md. A maintainer willing to break the world at 1.0 is a maintainer who may break it again at 1.1. We need a stated semver commitment for the profile API, the wire protocol, and the frontend caller API.
  • Protocol lock-in. Once files are tracked in chunky_* tables under a fingerprint scheme, switching away means migrating or abandoning in-flight uploads. Mitigated by the fact that final artifacts land on our own disks in our own paths — the durable output is portable even if the tracking layer is not.
  • Direct-to-S3 edge cases. Cloudflare R2 is documented as "best effort." If our storage strategy leans on R2, that is a caveat, not a feature. Requires bucket CORS with ExposeHeaders: ETag, which is an infrastructure change we must schedule with whoever owns the buckets.
  • Failure semantics are well-specified. Typed error codes (upload_expired, invalid_state, checksum_mismatch, lock_timeout) and retry-on-code rather than retry-on-message is exactly the contract we want. lock_timeout in that list tells us concurrency control is in play and can be a source of user-visible retries.
  • Bus factor of one. No evidence of a second maintainer. MIT license means we can fork, which is our real mitigation, but forking a PHPStan-max package with a TS monorepo is not free.

Key questions.

  1. What is the stated semver / deprecation policy for the profile contract and wire protocol post-1.0?
  2. Production references, even anonymized — has this carried real traffic, at what file sizes and concurrency?
  3. Who else holds commit/merge rights, and what is the response SLA on security reports?
  4. Is ChunkUploaded / chunk-POST idempotent, and how are duplicate final chunks handled?
  5. Where does a virus-scan or content-moderation hook attach — is completed() pre- or post-persistence on the final disk?
  6. What are the default chunk size and client concurrency, and are they tunable per profile?
  7. Is the fingerprint client-computed, and what prevents one user from resuming another user's upload by guessing a fingerprint?
  8. Does chunky:doctor cover the tracker driver and lock backend for the filesystem driver as thoroughly as the database driver?

Integration Approach

Stack fit. Ideal if we are on Laravel 12/13 + PHP 8.3 with any of Vue 3, React, Alpine, or Livewire already in the stack — all four are first-class. Blade + Alpine + Livewire shops get the least friction (<livewire:chunky-upload profile="avatar" /> is a drop-in). Teams on a non-supported frontend still have @netipar/chunky-core as a plain TS engine, which is the escape hatch.

Migration path. Brownfield has two shapes. For new upload surfaces, adopt Chunky directly — no migration. For existing upload endpoints, run Chunky alongside the legacy path behind a distinct route prefix (/api/chunky) and a distinct profile per use case, then cut over surface by surface. Do not attempt to migrate in-flight uploads; let the legacy path drain. The published chunky_* tables are additive and reversible, so a rollback is a route/config change plus a table drop, provided we have not yet made Chunky paths the only source of truth for media records.

Compatibility. Three hard checks before any commitment: (1) Laravel and PHP versions across all target apps; (2) whether the aws/aws-sdk-php requirement for direct_s3 conflicts with our existing SDK pin; (3) npm scope approval — whether our registry policy permits adding four @netipar/* packages and how we mirror/pin them. Also confirm the frontend packages' TypeScript/bundler expectations against our build (Vite is the safe assumption for Laravel).

Sequencing. Recommended five-step ramp:

  1. Spike (1–2 days). Single non-critical profile (e.g., internal avatar upload) in sync mode on a staging app. Exercise pause/resume/reload-resume, the fileChecksum verification path, and forced failure injection (kill the network mid-upload, expire an upload, corrupt a chunk).
  2. Config-gate validation. Wire chunky:doctor into the CI deploy gate with --wait for the queue probe; confirm it exits non-zero on a deliberately broken disk config.
  3. Instrument. Attach listeners to the eleven lifecycle events and ship them to our existing logging/metrics pipeline before any user traffic. Without this we are blind on failure rates.
  4. Pilot one real surface. Choose the highest-value, lowest-blast-radius upload (large documents, where resumability actually pays). Ship in auto mode so small files never touch a worker.
  5. Generalize. Add profiles per domain, enable direct_s3 only after the CORS change is confirmed and the R2 caveat is accepted or avoided, and only then consider batch uploads.

Build-vs-buy note. The realistic alternatives are (a) a tus-protocol stack, (b) an older chunk-upload package, or (c) in-house. In-house costs roughly the sum of: a resumable client, a chunk state machine, two tracker drivers, four framework adapters, and a protocol spec — weeks of work to reach parity with what is documented here. That asymmetry is the strongest argument for a spike. The weakest argument for a full commitment is the 0-star, single-maintainer profile.

Operational Impact

Maintenance. The package moves independently of our app. Budget a standing line item for version bumps and reading UPGRADE.md on minor releases, given the 0.x → 1.0 rewrite precedent. Our own maintenance surface is the profile classes — small, testable, and the natural place to own business logic. The typed config and boot-time validation mean config mistakes surface at deploy, which converts a class of runtime incidents into failed deploys. That is a good trade.

Support. No commercial support, no vendor. Our support story is: read the docs (they are genuinely good, in two languages, with an OpenAPI spec), read the source (it is small and typed), or fork. That is acceptable for a non-critical path and uncomfortable for a core revenue path. Recommend we do not put this behind a regulated or paid-critical upload flow until we have a quarter of clean production telemetry. Assign a named internal owner so the fork option stays credible.

Scaling. The auto mode with a 256 MB sync threshold is a sensible default but it is a web-worker ceiling: sync assembly holds a PHP request open while streaming a merge. Above the threshold it goes to queue, so we must have a worker running and monitored before we accept large-file use cases at volume. direct_s3 is the real scaling lever — PHP never touches bytes and S3 CompleteMultipartUpload is the assembly, eliminating the merge step entirely. If upload volume is a genuine dimension of the product, plan for direct_s3 as the end state, not sync. Concurrency on the client is a secondary tuning knob worth benchmarking rather than accepting blind.

Failure modes. The documented error envelope gives us a clean operational vocabulary:

  • Expired uploads (upload_expired) — expected under abandonment; must be paired with scheduled chunky:cleanup or the tracker table and chunk files grow without bound. This is the most likely self-inflicted incident: forgetting the cron entry. Put it in the deploy checklist, not just the README.
  • lock_timeout — concurrency contention; user-visible as retryable failure. Watch the rate; a rising rate means the chunk POST path is saturating.
  • checksum_mismatch — silent corruption caught, which is the good outcome, but it needs a client retry policy and a server-side alert.
  • Orphaned partial uploads — failed mid-assembly; again, chunky:cleanup is the janitor. Verify it removes both tracker rows and chunk artifacts on the filesystem driver.
  • Disk exhaustion — chunk staging plus final artifacts double the transient footprint. Capacity planning must account for staging, not just final files.
  • S3 CORS / missing ETag — the classic direct-to-S3 breakage; surfaces as client-side failures that look like network errors. Test the CORS recipe in staging, not production.
  • Queue worker absent while in queue mode — the worst UX failure: uploads hang at "assembling" with no error. This is precisely what chunky:doctor's worker probe exists to prevent; wire it into the deploy gate and into a periodic health check.
  • Broadcasting enabled without sanitization review — payloads are documented as sanitized and versioned (disk, final_path, user_id withheld), but we should verify on our own before trusting it in a multi-tenant context.

Ramp-up. Backend engineers already fluent in Laravel need hours, not days — the profile class is idiomatic and the quickstart is accurate. Frontend engineers need a mental-model shift on one point: unmounting a component unsubscribes, it does not cancel. Teams conditioned to useEffect cleanup killing requests will get this wrong and will report "uploads vanish on navigation" as a bug. Put it in the onboarding note. Add manager.installUnloadGuard() early so real page unloads warn, while SPA navigation stays silent — that distinction is only obvious once explained. Budget roughly one engineer-week for the spike plus instrumentation, and gate the broader rollout on a fortnight of telemetry showing a chunk-retry rate and lock_timeout rate we are happy with.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel