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

Cursor Pagination Laravel Package

laravel-json-api/cursor-pagination

Cursor-based pagination for Laravel JSON:API. Adds a cursor paginator so your JSON:API endpoints can page through large datasets efficiently, avoiding offset limits and keeping results stable as records change.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Choosing a pagination contract per surface, not globally. Cursor pagination trades jump-to-page, arbitrary page addressing, and cheap totals for stable, cheap deep pages. That trade belongs to specific surfaces: mobile feeds, notification lists, activity and audit logs, transaction histories, message threads, and background sync/export jobs all consume results sequentially and are visibly broken by the duplicate-and-skip rows that offset pagination produces when data changes mid-scroll. Admin tables with sortable columns and "page 7 of 42" want the offset paginator the framework already ships. This package makes the cursor option affordable enough to be argued on product merit rather than engineering cost.
  • Fixing a class of bug rather than shipping a feature. Duplicate and skipped records during scrolling are a correctness defect that generates support tickets and erodes trust in exports and sync jobs. This is a cheap, narrow remedy for an existing defect on high-churn list endpoints — a quality decision, not a roadmap expansion.
  • Build vs. buy for pagination plumbing. The realistic alternative is a one-to-three-day in-house implementation of cursor encoding, page[cursor]/page[size] parameters, and spec-shaped links/meta over Laravel's native cursorPaginate(). With zero dependents and a single maintainer, "buy" realistically means adopting a few hundred MIT-licensed lines — vendor or fork them — rather than consuming a supported dependency. That reframes the decision as "do we want to own this source," which is answerable.
  • Performance and infrastructure budget. Keyset pagination is roughly O(log n) per page versus OFFSET's linear cost, which can defer read-replica or index spend on deep list views — but only if a composite index matching the exact sort tuple exists. Approval should bundle that index as a prerequisite, not a follow-up, otherwise the change is a net slowdown.
  • Whether JSON:API is already committed. This is binary and upstream: the package is a pagination-profile add-on to laravel-json-api and has no value outside that stack. It cannot inform "should we do JSON:API"; it only answers "we are on JSON:API, how do we paginate it." Framing it that way in roadmap discussions prevents it from being mistaken for general pagination investment.
  • Rollout and API-contract scope. Per-endpoint opt-in behind a flag or new API version, not a fleet-wide cutover. That decision sets how much client-facing contract communication is required, what we tell front-end teams about the deliberate absence of total/last, and how quickly the change can be reversed.
  • Ownership model. The real question surfaced is not "is the feature desirable" (it is) but "will we own the source." With essentially no community validation, the approvable framing is a named internal owner plus vendoring — not a line in composer.json.

When to Consider This Package

Consider it when:

  • The service already exposes a JSON:API surface via laravel-json-api, and a client or the spec requires cursor pagination.
  • A specific list endpoint sits on a large or write-heavy table where OFFSET cost or result instability has been measured — duplicate or skipped rows in logs, slow deep pages — not merely assumed.
  • Consumers are sequential: mobile apps, background sync, exports, where "next page only" is acceptable or preferable to page addressing.
  • A deterministic unique sort tuple (created_at, id) can be mandated per endpoint, with a matching composite index signed off before shipping.
  • The team accepts vendoring or forking the source under an internal namespace with a named owner, and can fund a roughly one-day spike to verify link shapes, cursor behavior, and 400 error mapping against the pinned parent version.

Look elsewhere when:

  • The product is not on laravel-json-api. Call cursorPaginate() directly; there is no integration surface here. Same answer for API Resources, Fractal, spatie/laravel-query-builder, GraphQL, gRPC, and plain REST.
  • UX requires page numbers, jump-to-page, or accurate totals — use the offset/page-based paginators the parent framework ships.
  • Consumers need bookmarkable, long-lived, or cross-endpoint cursors, or cryptographically signed cursors with versioning. At that point in-house code is clearer than patching a dependency.
  • The organization requires a supported dependency with an SLA, security-response process, or active release cadence. Three stars and zero dependents mean no community validation and no bus factor.
  • Datasets are small and read-mostly, where offset pagination is simpler, universally understood, and the instability never materializes.

How to Pitch It (Stakeholders)

For executives. This is a small, MIT-licensed add-on that lets our API serve long, continuously updating lists — feeds, activity logs, transaction history — without the duplicate-and-skip bugs and database cost of page-number pagination. It is cheap to evaluate (about a one-day spike) and cheap to own if we vendor it. The caveat is material and should be stated up front: effectively no community adoption and a single maintainer, so we treat it as source code we adopt, not a vendor product we depend on. Recommended posture: pilot on one endpoint behind a flag, fund a small amount of engineering time to own the code, and keep it off any critical path that lacks that ownership plan. It is also only relevant if we have already committed to JSON:API — if we have not, this is not the lever.

For engineering. It plugs into laravel-json-api as a pagination implementation, wrapping Laravel's native cursor paginator and emitting spec-shaped cursor links with page[cursor] and page[size]. The integration surface is narrow — a pagination class plus per-resource registration — so a spike should land under a day, including verifying behavior under concurrent inserts. Three things we must own in application code because the package cannot: a deterministic unique sort tuple (created_at, id) on every paginated endpoint, rejection or restart when the requested sort differs from the sort embedded in the cursor, and clean JSON:API 400 responses for malformed or stale cursors instead of 500s. Verify explicitly whether cursors are tamper-evident — base64-encoded sort values can be forged to probe outside an authorized filter set, which is an authorization concern, not a polish item. Confirm too whether relationship endpoints and nested filters are covered, and that omitting total/last is deliberate and documented, since front-end teams will assume they exist. Risks are provenance rather than code quality: Page contract drift on parent upgrades, no external CI signal to lean on, and edge cases (empty pages, cursor expiry, relation-heavy includes, NULL semantics, MySQL/PostgreSQL/SQLite collation differences) that become ours to find. Mitigation is straightforward: vendor or fork under an internal namespace, add characterization tests for link generation and stability under writes, keep the abstraction at the resource layer so clients are unaffected by a swap to in-house code, and run a CI job against the parent's next minor for early drift warning. If we are not already committed to JSON:API, do not adopt this — call cursorPaginate() directly.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource