Skip to content

Mastering Laravel Cursor Pagination: A Guide to Superior Performance

Boost your Laravel app's performance with cursor pagination. Our guide explains how to implement cursorPaginate() for faster results & seamless infinite scrolling on large datasets.

Dasun Kalupahana 3 min read 1.2K views 0 comments

Introduction

In web development, efficiently handling large datasets is a common challenge. Traditional Laravel pagination, while simple, can become a performance bottleneck as your data grows. Cursor pagination, introduced in Laravel 8.41, offers a powerful alternative. This guide will explain what cursor pagination is, how it works under the hood, and provide practical code examples to help you implement it for a faster, more scalable application.

Key Differences: Cursor Pagination vs. Offset Pagination

To understand the benefits of cursor pagination, it's best to compare it directly with the traditional offset-based method.

Feature

Cursor Pagination (cursorPaginate)

Offset Pagination (paginate)

Underlying Query

Uses a WHERE clause (e.g., WHERE id > 15)

Uses LIMIT and OFFSET (e.g., LIMIT 15 OFFSET 15)

Performance on Large Datasets

Excellent; performance remains constant regardless of page depth

Poor; gets slower on deeper pages as the database must scan more row

Data Consistency

High; immune to duplicates or skipped records from frequent writes

Low; inserts or deletes can cause record duplication or skipping

User Interface & Navigation

"Next" and "Previous" links only (similar to simplePaginate)

Full page number navigation, showing total page count

Ideal Use Cases

Large datasets, infinite scrolling, APIs, real-time data feed

Smaller datasets, applications where users need to jump to specific pages



How to Implement Cursor Pagination in Laravel

Implementing cursor pagination in your Laravel application is straightforward. The syntax is very similar to other pagination methods.


1. Basic Backend Implementation
In your controller, use the cursorPaginate method on your Eloquent query builder. It is crucial to have an orderBy clause, preferably on a unique column like the primary key

<?php
// UserController.php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index()
    {
        // Paginate users using a cursor, ordered by 'id'
        $users = User::orderBy('id')->cursorPaginate(10);

        return view('users.index', compact('users'));
    }
}

2. Frontend Display in Blade Templates
The object returned by cursorPaginate can be iterated and used to generate links, much like traditional paginators.

<!-- resources/views/users/index.blade.php -->

<h1>Users</h1>

@foreach ($users as $user)
    <p>{{ $user->name }} - {{ $user->email }}</p>
@endforeach

<!-- Display pagination links -->
{{ $users->links() }}

<!-- Or, for a simpler "Next Page" approach: -->
@if ($users->hasMorePages())
    <a href="{{ $users->nextPageUrl() }}">Load Next Page</a>
@endif

3. JSON Response for APIs
When used in an API controller, cursorPaginate returns a JSON structure that includes the data and the necessary cursor URLs.

// API Controller
public function getUsers()
{
    $users = User::orderBy('created_at')->cursorPaginate(15);
    return response()->json($users);
}

Example JSON response structure:

{
  "data": [ ... ],
  "path": "https://yourapp.com/api/users",
  "per_page": 15,
  "next_page_url": "https://yourapp.com/api/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0",
  "prev_page_url": null
}


Key Benefits and Advantages

  • Superior Performance: By avoiding the OFFSET clause, the database doesn't need to scan through all previous records. This makes cursor pagination hundreds of times faster for deep pages in large datasets

  • Data Consistency for Real-time Data: Cursor pagination prevents the "page drift" issue common in offset pagination. When records are added or deleted, users won't see duplicate or missing items as they page through results, making it perfect for live, updating feeds

  • Efficiency: It does not perform a costly COUNT query on the entire dataset, which further enhances performance on large tables



Important Limitations and Requirements

  • No Page Number Navigation: You cannot jump to a random page. Navigation is strictly sequential—"next" and "previous".

  • Unique Ordering Clause: The column(s) you use in the orderBy clause must be unique. If you order by a non-unique column like name, you must add a second unique column (like id) to break ties.

// Good: Using a unique column or combination
$users = User::orderBy('created_at')->orderBy('id')->cursorPaginate(10);
  • Database Indexes are Crucial: To achieve the performance boost, the columns used for ordering must be indexed. Without an index, the performance benefit is lost.



Conclusion
Laravel's cursor pagination is a powerful tool for any developer building scalable, high-performance applications. It solves critical problems of performance and data consistency that arise with large or rapidly changing datasets. While it sacrifices the ability to jump to specific page numbers, the benefits for infinite scrolling, API responses, and large data tables are undeniable.

By following the implementation examples and understanding its characteristics, you can make an informed decision to use cursor pagination where it provides the most value.

If you found this helpful, feel free to share or drop a comment. Happy coding with Laravel! 🧱✨

Free resources for this topic

Code snippets and fixes for this topic

Get one practical tip every week

New tutorials, fixes and free cheat sheets from DEV Talk, straight to your inbox. No spam, unsubscribe in one click.

Free download: Laravel interview questions (PDF)

Have a question about this post?

Ask the community: other developers and the author can answer.

Ask the community

Get notified about new articles

One click, no email needed. Turn it off anytime with the bell at the top.

Get new articles on your iPhone

Add DEV Talk to your Home Screen, open it, then tap the bell.

Rate this post
5.0
Share

Enjoying the content?

If this article helped you, you can support the author with a coffee. It keeps new posts coming.

Buy me a coffee (opens in a new tab)

Comments 0

Be kind. Comments with links are reviewed before they appear.

No comments yet

Be the first to share your thoughts.

Get new articles in your inbox

Practical tutorials and deep dives, about once a week. No spam, unsubscribe anytime.

Privacy policy

Add DEV Talk to your Home Screen

  1. 1 Tap the Share button in Safari's toolbar.
  2. 2 Scroll down and tap Add to Home Screen.
  3. 3 Tap Add. Open it from the Home Screen to read like an app and to turn on notifications with the bell.

We use cookies to improve your experience and analyze traffic. By continuing, you agree to our Privacy Policy.