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

Fast Paginate Laravel Package

hammerstone/fast-paginate

Laravel pagination macro for large tables: swap paginate() for fastPaginate() and it fetches just the IDs for the current page via a subquery, then joins them back—avoiding slow deep offsets. Drop-in replacement for Eloquent builders, no config or view changes needed.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Performance roadmap triage. fastPaginate() is a drop-in swap for paginate() that removes the SELECT COUNT(*) that Laravel runs on every paginated request, replacing it with a bounded subquery (... LIMIT offset+perPage+1). This lets a PM decide between three options with real data: (a) ship a one-line package change this sprint, (b) schedule a cursor-pagination redesign next quarter, or (c) invest in read replicas / count caching. The package buys time for (b) at near-zero cost, which is usually the correct sequencing.
  • API contract decisions. Adopting it forces an explicit decision about whether clients actually need total and last_page. That is a product question, not an engineering one. Numbered page links ("Page 47 of 312"), "showing 1–20 of 4,382 results," and CSV export-by-page-count all depend on the count query. Deciding to drop or defer those is a roadmap call the package surfaces.
  • Enabling "Load more" / infinite scroll. The package is a natural fit for feed-style UIs where the user never asks "how many total?" Removing the count makes the read path cheap enough to serve at higher request volumes without new infrastructure.
  • Build vs. buy. ~1.4k stars, MIT, and a deliberately small surface area (one query builder macro, essentially). Build cost is low — a senior engineer could reimplement it in an afternoon — but so is adoption cost. Recommend adopt, with a documented escape hatch: the code is small enough to vendor into the app if the maintainer disappears. The "0 dependents" signal is misleading here; it reflects Packagist metadata, not real-world usage, and total integration surface is one method call.
  • Cost and capacity planning. Fewer full-table counts means less CPU and I/O per request. Quantify as: paginated endpoint P95 latency, DB CPU attributable to count queries, and headroom gained before the next instance size. That is the number to put in the business case.
  • Admin and internal tooling. Back-office tables over large tenant datasets are the highest-value, lowest-risk first target: internal users tolerate "next/previous" without page numbers, and the tables are often the worst offenders.

When to Consider This Package

Adopt when most of the following hold:

  • You have Laravel paginated endpoints where COUNT(*) is the dominant cost — typically tables in the millions of rows, or queries with expensive WHERE/JOIN clauses where the count has to scan the same working set as the page.
  • The UI or API consumer does not strictly require total / last_page. "Next" and "Previous" affordances are acceptable.
  • You want a change measured in minutes, not sprints: one method call per query, no schema migration, no client changes beyond removing a total-count display.
  • Your queries are reasonably simple — flat WHERE/ORDER BY, or joins that survive being wrapped in a LIMIT-bounded subquery.
  • You are prepared to own the ~200 lines if the single maintainer steps away. Given the license and size, fork risk is negligible.

Look elsewhere when any of these are true:

  • Totals are contractual. Financial statements, compliance exports, "N results found," or anything where a client computes page numbers. You will need the real count from somewhere.
  • Deep offsets are the actual problem. LIMIT 20 OFFSET 200000 is still slow with or without a count. That is a cursor/keyset pagination problem (cursorPaginate() is built into Laravel), not a counting problem. Adopting this package here treats a symptom.
  • Unstable sort order under concurrent writes. Offset pagination already drifts; the package doesn't change that, and removing totals can make drift harder to spot in support tickets.
  • Exotic query shapes — groupBy, having, distinct, unions, or CTEs where wrapping the select in a bounded subquery changes semantics or fails outright. Budget engineering validation time for each paginated endpoint, not a blanket find-and-replace.
  • Small tables. Under ~100k rows the count is cheap; you're adding a dependency and a behavioral difference for zero measurable gain.
  • You need the full Laravel paginator API — total(), lastPage(), page-number link rendering, onEachSide, and withQueryString interactions all need review. Treat "same interface" as approximately true, not exactly true.

How to Pitch It (Stakeholders)

To executives: We have a class of API endpoints that are slow and expensive purely because of a row-count query Laravel runs on every page load — a query whose result we display but rarely act on. This package replaces that count with a bounded query that stops scanning as soon as it has enough rows to know whether a next page exists. The change is roughly one line per endpoint, requires no schema or client changes in the common case, is MIT-licensed, and is small enough that we could maintain it ourselves. The trade is that we lose exact result totals on those screens — a product concession, not a technical one — which we should confirm per surface before rollout. Expected outcome: lower database cost and faster page loads on our heaviest list views, delivered in days, while we scope a proper cursor-pagination redesign for the long term without an outage forcing our hand. Risk is low and reversible: the change is per-query and can be reverted individually.

To engineering: This is a maintenance-light dependency, not a framework commitment. It exposes fastPaginate() as a builder macro; the implementation wraps the existing query in a LIMIT offset+perPage+1 subquery and counts that, so the database short-circuits instead of scanning the full working set. Things to verify before rollout: endpoints that read total()/lastPage() or render numbered links; any groupBy/having/distinct queries, which may not wrap cleanly; and tests asserting on pagination metadata. The package is small, MIT, and easy to vendor or fork if the maintainer goes quiet, so treat it as an internal utility with an upstream — not a strategic bet. Measure before/after with query timing and DB CPU on two or three representative endpoints; if the count wasn't the bottleneck, roll it back and we've learned something cheap.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource