When an API database grows to hundreds of thousands of records, returning entire datasets crashes client applications and exhausts server memory. Production REST APIs require Pagination (chunking results into manageable pages), Dynamic Filtering (querying by status, date, or author), and Multi-Column Sorting (ordering by price, date, or popularity).
| Pagination Type | Method Call | SQL Mechanism | Performance on 1 Million Rows |
|---|---|---|---|
| LengthAware (Offset) | Article::paginate(15) |
LIMIT 15 OFFSET 50000 |
Slow on large offsets (requires full table scan) |
| Simple Pagination | Article::simplePaginate(15) |
LIMIT 16 OFFSET 50000 |
Faster (Omits heavy SELECT count(*) query) |
| Cursor Pagination | Article::cursorPaginate(15) |
WHERE id > 50000 LIMIT 15 |
Sub-millisecond constant speed! Ideal for infinite scrolls |
Avoid messy if ($request->has(...)) chains in your controller by using Eloquent's when() helper:
public function index(Request $request)
{
$articles = Article::query()
// 1. Text Search Filter
->when($request->filled('search'), function ($query) use ($request) {
$query->where(function ($q) use ($request) {
$q->where('title', 'like', "%{$request->search}%")
->orWhere('body', 'like', "%{$request->search}%");
});
})
// 2. Status Filter
->when($request->filled('status'), fn ($q) => $q->where('status', $request->status))
// 3. Category Filter
->when($request->filled('category_id'), fn ($q) => $q->where('category_id', $request->category_id))
// 4. Dynamic Sorting with Whitelist
->when($request->filled('sort'), function ($query) use ($request) {
$sortColumn = ltrim($request->sort, '-');
$direction = str_starts_with($request->sort, '-') ? 'desc' : 'asc';
// Security: Strictly whitelist allowed sort columns
if (in_array($sortColumn, ['title', 'created_at', 'views'])) {
$query->orderBy($sortColumn, $direction);
}
}, fn ($query) => $query->latest()) // Default sort
->cursorPaginate(20);
return ArticleResource::collection($articles);
}
For enterprise APIs, the gold standard is spatie/laravel-query-builder. It supports standard JSON:API specifications (e.g. GET /api/v1/articles?filter[status]=published&sort=-created_at&include=author) in two lines of code:
use Spatie\QueryBuilder\QueryBuilder;
use Spatie\QueryBuilder\AllowedFilter;
$articles = QueryBuilder::for(Article::class)
->allowedFilters(['title', AllowedFilter::exact('status'), 'category_id'])
->allowedSorts(['title', 'created_at', 'price'])
->allowedIncludes(['author', 'comments'])
->paginate(15);
Broaden your backend architecture, REST API design, and enterprise production engineering expertise:
Design clean query parameter standards (?sort=-created_at&filter[status]=active).
Cache paginated API responses to reduce database load during traffic spikes.
Execute performant database count queries and cursor-based offsets.
Build an API catalog filter with multiple parameters and pagination controls.