Pagination in Mobile Development — What It Is, Types, and How It Works

Author: IT Sectr Published: 2026-03-11 Reading time: 9 min

Pagination is a technique for loading data in pages, used in mobile applications and web services to handle large sets of records. According to Android Developers Documentation (2025), proper pagination implementation reduces API load, saves traffic, and improves user experience. Page-by-page loading allows an application to display content gradually without waiting for all data to load at once.

Key Takeaways

  • Pagination is a method of loading large datasets in chunks to optimize performance and traffic.
  • Offset pagination uses an offset (page/offset) for navigation — simple but unstable with frequent insertions.
  • Cursor pagination uses a unique cursor from the last record — stable when data changes between requests.
  • Keyset pagination filters by a column with a unique index — efficient for large tables without duplicates.
  • Time-based pagination groups records by timestamps — convenient for news feeds and social networks.

What Is Pagination?

Pagination (from Latin pagination — page division) is a technique of splitting a large dataset into sequential portions (pages). In mobile applications, pagination is used when loading message lists, news feeds, product catalogs, order history, and any other collections with a potentially unlimited number of records.

Without pagination, an application has to load all data at once, leading to long wait times, high traffic consumption, and unstable performance on low-end devices. An API request with pagination returns only one portion of data along with meta-information for loading the next one — thus, the application controls the amount of information it receives.

The main pagination metrics are: page size — the number of records per page (usually 10–50), and page number or cursor — a pointer to the current position in the dataset. The choice of page size depends on the type of data: for compact elements (names) 20–30 is enough, for cards with images — 10–15.

Why Pagination Is Needed in Mobile Apps

Mobile devices have limited resources: RAM, CPU speed, and traffic limits. Pagination solves three key tasks: reduced memory consumption (only visible elements are stored in memory), faster first render (the first portion loads faster than the entire dataset), and traffic savings (data is loaded only when the user scrolls the list).

Main Types of Pagination

There are four main types of pagination, each solving specific tasks. The choice of method depends on data consistency requirements, API architecture, storage type, and acceptable implementation complexity on the client and server sides.

TypeHow It WorksStabilitySpeed on Large Volumes
OffsetLIMIT + OFFSET in SQLlowdegrades with growing OFFSET
CursorWHERE id > last_idhighstable (O(log n))
KeysetWHERE key > last_keyhighstable (O(log n))
Time-basedWHERE created_at < last_timemediumstable with an index

When to Use Which Type

Offset pagination is suitable for static or rarely updated datasets where simple implementation matters. Cursor and Keyset are for dynamic data with frequent insertions. Time-based is for chronological feeds where records are ordered by creation time. The GraphQL standard Relay uses cursor pagination as the only recommended method.

Offset Pagination: Advantages and Disadvantages

Offset pagination is the simplest type of page-based loading. The client passes page and limit (or offset and limit) parameters, and the server applies SQL OFFSET and LIMIT. For example, page=2, limit=20 returns records 21 through 40. This method is intuitive and easy to implement on any stack.

python
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items")
async def get_items(
    page: int = Query(default=1, ge=1),
    limit: int = Query(default=20, le=100)
):
    offset = (page - 1) * limit
    items = await fetch_items(offset, limit)
    total = await count_items()
    return {
        "items": items,
        "total": total,
        "page": page,
        "pages": (total + limit - 1) // limit
    }

The Data Inconsistency Problem

The main drawback of Offset pagination is the problem of missing and duplicate records. If new records are added to the table between two requests, the OFFSET shifts: the user may see the same record twice or miss a new one. This is critical for news feeds and chats where consistency matters.

Another problem is performance degradation on large OFFSET values. The database has to scan and skip the first offset records before returning the result. At offset=100000 even with LIMIT 20, the server will spend noticeable time scanning. PostgreSQL and MySQL show a linear drop in speed as OFFSET grows.

When Offset Is Still Good

Offset pagination remains the best choice for: admin panels (data rarely changes, page navigation is needed), reports and historical logs (fixed data snapshot), filtered catalogs (you can jump to any page). Offset is also the simplest to implement on the client — RecyclerView with Paging 3 supports it out of the box.

Keyset and Time-based Pagination

Keyset pagination uses a unique key (usually the primary key) to filter records. Instead of OFFSET, the query uses WHERE id > last_seen_id. This ensures stable performance regardless of the number of records and no duplicates on insertions, since new records always have a larger id.

sql
-- Offset pagination (problematic)
SELECT * FROM posts
ORDER BY id
LIMIT 20 OFFSET 100;

-- Keyset pagination (stable)
SELECT * FROM posts
WHERE id > 100
ORDER BY id
LIMIT 20;

Time-based Pagination

Time-based pagination (or cursor by time) uses the created_at timestamp for navigation. The client passes the timestamp of the last loaded record, and the server returns records created before or after that timestamp. This method is popular in social networks and news feeds where the order of records is determined by publication time.

A feature of Time-based pagination is possible duplicates if two records are created in the same millisecond. To eliminate this issue, combine a time-based key with a unique id: WHERE (created_at, id) < (last_time, last_id). Such a composite cursor guarantees uniqueness of each record and precise ordering.

Comparison of Keyset and Time-based

Keyset pagination requires a column with a unique and monotonically increasing value (auto-increment id, UUID v7). Time-based is suitable for any table with created_at but requires additional duplicate handling. The main difference: Keyset works stably under any insert operations, while Time-based is sensitive to identical timestamps.

How to Choose a Pagination Type for Your Project

The choice of pagination type depends on the nature of the data and user experience requirements. Below are recommendations for typical scenarios in mobile development. There is no universal solution — each method has a domain where it is optimal.

  • Chat / Messenger — Cursor pagination (by message id). New messages appear at the top, cursor does not break.
  • News Feed — Time-based pagination (by created_at). Records are ordered by time, chronology matters.
  • Product Catalog — Offset pagination. Users can jump to a specific page, data rarely changes.
  • Order History — Cursor pagination. Stability matters because new orders are added between loads.
  • Comments — Keyset pagination. Each comment has a unique id, large volumes without duplicates.

Android Implementation with Paging 3

The Android Paging 3 library supports all pagination types through PagingSource. For Offset — PagingSource with Int key (page), for Cursor — with String or Long key (cursor). PagingSource automatically manages loading, caching, and retry on errors.

kotlin
class PostPagingSource(
    private val api: PostApi
) : PagingSource<Long, Post>() {

    override suspend fun load(
        params: LoadParams<Long>
    ): LoadResult<Long, Post> {
        val cursor = params.key ?: Long.MAX_VALUE
        return try {
            val response = api.getPosts(cursor, params.loadSize)
            LoadResult.Page(
                data = response.items,
                prevKey = null,
                nextKey = response.items.lastOrNull()?.id
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<Long, Post>): Long? {
        return state.anchorPosition?.let {
            state.closestItemToPosition(it)?.id
        }
    }
}

Page Size Recommendations

Page size affects loading speed and perceived performance. For mobile applications, the optimal range is 10–25 items per page. Fewer than 10 results in too many API requests and janky scrolling. More than 25 results in slow initial load on slow networks.

For images and videos, reduce page size to 5–10, since each element takes additional time to load media. For text-based lists (comments, logs), the size can be increased to 30–50 records. It is recommended to make page size configurable via the API so the client can adapt to different network conditions.

Frequently Asked Questions

What is pagination in simple terms?

Pagination is loading data in portions rather than all at once. Like a book: you read one page, then turn to the next. In an app, this means that when you scroll through a list, the next batch of data loads, not the entire list at once, saving traffic and memory.

How is Offset different from Cursor pagination?

Offset counts records: “skip 20, return the next 10.” If a new record is added between loads, the numbering breaks. Cursor uses the unique identifier of the last record: “return 10 records after ID = 100.” New records do not affect the position.

What is the optimal page size for pagination?

For mobile applications, 10–25 items is optimal. For image-heavy lists — 5–10, for text feeds — 20–30. The size depends on the average element size: the heavier the element, the smaller the page should be for fast display.

How to implement pagination in RecyclerView?

Use the Paging 3 library from Android Jetpack. It provides PagingSource for loading, PagingData for reactive streams, and PagingDataAdapter for automatic loading on scroll. The library supports Offset, Cursor, and Keyset pagination through a custom PagingSource.

What is infinite scroll and how is it different from pagination?

Infinite scroll is a UI pattern where a new batch of data loads automatically as the user approaches the end of the list. Pagination is the mechanism of loading data in batches, while infinite scroll is one way to display it. An alternative is the “Load more” button.

Summary

  • Pagination is a technique for loading data in portions, essential for mobile apps with any kind of list.
  • Offset pagination is simple to implement but suffers from inconsistency on insertions and performance degradation on large OFFSET values.
  • Cursor pagination uses a unique identifier for navigation — stable and efficient on any volume.
  • Keyset pagination filters by primary key, providing maximum performance through index usage.
  • Time-based pagination groups records by timestamps — ideal for chronological feeds and social networks.
  • Choosing a method depends on data nature: for dynamic data — Cursor/Keyset, for static — Offset, for feeds — Time-based.
  • Paging 3 on Android and standard cursor solutions on iOS/web provide ready infrastructure for any pagination type.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also