Comparing Limit-Offset and Cursor Pagination
Tags: database, backend
Published: 2024-07-10 01:56:38

## Comparing Limit-Offset and Cursor Pagination
There are two popular methods for pagination that are `limit-offset pagination` and `cursor pagination`. Each has its own strengths and weaknesses, making them suitable for different scenarios. Let's explore these methods, comparing their performance, complexity, and use cases.

## Limit-Offset Pagination

**How It Works:**
Limit-offset pagination is straightforward and involves two main parameters:
1. **Limit**: The number of records to fetch.
2. **Offset**: The number of records to skip before starting to fetch the records.

On the user interface side, users typically see pages instead of limit-offset pairs. However, behind the scenes, these pages are converted to limit-offset using the following simple formula:

- limit = page size
- offset = (page number - 1) x page size

For example, in SQL, a query using limit-offset pagination might look like this:
```sql
SELECT * FROM articles ORDER BY id DESC LIMIT 10 OFFSET 20;
```
This query fetches 10 articles, skipping the first 20 (corresponds to page 3 with a page size of 10).

**Pros:**
1. **Simplicity**: Easy to understand and implement.
2. **Flexibility**: Allows direct access to any page of the results.

**Cons:**
1. **Performance**: Can become slow with large offsets since the database has to scan and discard the rows before the offset. 
2. **Inconsistency**: Results can become inconsistent if the underlying data changes between queries. This is problematic in dynamic datasets where records are frequently added or removed.

## Cursor Pagination

**How It Works:**
Cursor pagination, also known as keyset pagination, uses a unique identifier (cursor) to mark the position in the dataset. Instead of using offset, it fetches records after the last retrieved record based on the cursor.

For example, a query might look like this:
```sql
SELECT * FROM articles WHERE id > 100 ORDER BY id ASC LIMIT 10;
```
Here, `100` is the cursor representing the last seen `id`.

**Pros:**
1. **Performance**: More efficient for large datasets since it avoids scanning and discarding rows.
2. **Consistency**: More consistent results in dynamic datasets as it is less affected by changes in the data.

**Cons:**
1. **Complexity**: Slightly more complex to implement, especially in maintaining the cursor state.
2. **Flexibility**: Less flexible in accessing arbitrary pages directly, as you must traverse sequentially from the start.

I recommend `against` exposing the ID directly for use as a cursor. The auto-incremented ID is sensitive information. It not only reveals the sequence of records but also exposes the total number of records through the last ID.

You can encrypt it before exposing, and then decrypt it upon receipt to prevent exposure of the raw value.


## Performance Comparison

**Limit-Offset Pagination:**
- Performance can degrade with high offset values due to the need to scan and discard many rows.
- Simple queries but can cause heavy load on the database in scenarios with deep pagination.

**Cursor Pagination:**
- Maintains high performance even with large datasets since it works by directly accessing the position marked by the cursor.
- Better suited for applications with continuous scrolling or infinite scroll patterns where users do not need to jump to arbitrary pages.

## Use Cases

**Limit-Offset Pagination:**
- Ideal for scenarios with relatively small datasets or where the need to jump to specific pages outweighs performance concerns.
- Suitable for static data where the likelihood of data changes between requests is low, such as paginated static reports.

**Cursor Pagination:**
- Best for applications dealing with large datasets or requiring high-performance pagination, such as social media feeds, activity streams, or scanning data for ETL tasks.
- Useful in dynamic environments where data changes frequently, ensuring more consistent user experiences.

## Conclusion

Choosing between limit-offset and cursor pagination depends on the specific needs and constraints of your application. 
- Limit-offset pagination offers simplicity and flexibility but can suffer from performance issues with large datasets. 
- Cursor pagination provides better performance and consistency, making it ideal for large or dynamic datasets, though it requires a bit more implementation effort.