itsimiro/laravel-chunk-cursor
Iterate large Eloquent result sets with cursor-based chunking instead of offset pagination. Process millions of rows in constant memory with stable ordering, avoiding skipped or duplicated records as data changes. Simple drop-in methods for Laravel query builders.
Feature feasibility — bulk/large-dataset features stop being scary. Any roadmap item that means "process every row in a big table" is now a smaller estimate. Concretely, this unblocks or de-risks:
cursor() OOMs on relations (N+1) and chunk() blows the query budget.Build vs. buy — this is really "adopt vs. copy." At ~2 stars, 0 dependents, a single maintainer, and no release since April 2024, this is not a dependency decision; it's a snippet decision. The honest framing for the team: the concept (chunked cursor + eager loading) is worth adopting; this specific artifact is worth reading, not necessarily installing. Budget roughly half a day to a day to implement the equivalent as an internal base-repository trait or query macro, which removes the supply-chain and upgrade risk entirely.
What it buys you against the framework baseline: Laravel's chunk()/chunkById() support eager loading but issue a query per chunk (and chunk() can skip/duplicate rows if the dataset mutates underneath it); cursor() is memory-optimal but cannot eager load, so relations degrade to N+1. This package targets the gap between those two. That gap is real — validate it against your actual slowest job before committing.
Success metrics to instrument before and after: peak worker memory (MB), wall-clock runtime, query count per 10k rows, and failure/timeout rate on the largest job. If you can't show a memory or query-count win on a real job, don't adopt it.
Good fit:
cursor() already solves it and you need nothing).Look elsewhere / pass:
chunkById/lazyById semantics (strict id > last keyset pagination) with explicit ordering guarantees. Confirm the package gives you keyset behavior, not offset, before relying on it.To executives: There's a small open-source utility that makes "process every record in a large table" jobs cheaper and safer — lower memory, fewer database round-trips, no midnight timeouts. It's not a strategic bet and it's not a platform commitment; it's a pattern worth ~one engineer-day. The package itself is immature (tiny community, single maintainer, no recent release), so the recommendation is to adopt the technique internally rather than take a dependency on it. Expect a modest reduction in incidents on export and sync jobs, and slightly better estimates on bulk-data features.
To engineering: It fills a genuine gap — chunked iteration with eager loading, which cursor() can't do and chunk() does wastefully. Risk profile is low because the code is small and MIT: read it, benchmark it against lazyById() on our worst-performing job, and if it wins, either pin it behind an internal ChunkedCursor interface with a fallback implementation, or reimplement it in the base repository. Do not let it leak into feature code directly — that keeps the swap-out cost near zero if it goes unmaintained.
How can I help you explore Laravel packages today?