Introduction

When a Power Apps Canvas App works with a large number of records, displaying everything at once can make the application difficult to use and may affect performance.

Pagination provides a simple solution by dividing records into smaller pages, such as 25 records per page, and allowing users to navigate using Next and Previous buttons.

What Is Pagination?

Pagination means dividing a large dataset into smaller groups called pages.

For example, if a Dataverse table contains 1,000 customer records:

Code
Page 1  → Records 1–25
Page 2  → Records 26–50
Page 3  → Records 51–75
...
Page 40 → Records 976–1000

Instead of displaying all 1,000 records together, the app displays only the records required for the current page.

Benefits

  • Better user experience

  • Smaller data payload

  • Easier navigation

  • Better control over large datasets

  • Useful for grid-style applications

When Should You Use Pagination?

Pagination is useful when your business requirement includes:

  • Page numbers

  • Next and Previous buttons

  • Fixed records per page

  • Navigation through a large result set

  • A traditional table or grid experience

For example:

Code
Customer List

Customer Name       City        Status
----------------------------------------
ABC Ltd             Mumbai      Active
XYZ Ltd             Pune        Active
ABC Corporation     Delhi       Inactive
...

[Previous]     Page 1     [Next]

However, pagination isn't always necessary.

If users mainly need to search, filter, or sort, it is often better to use delegable queries directly against the data source.

Two Common Approaches

There are two approaches you should understand.

1. Automatic Data Loading

If a Gallery is directly connected to a remote data source:

Code
Gallery1.Items = Customers

Power Apps can retrieve data incrementally as needed.

This is the simplest approach when you don't need explicit page numbers.

Use this when:

Code
Users need:
✓ Search
✓ Filter
✓ Sort
✓ Scroll through records

2. Custom Pagination

If the business specifically requires:

Code
Page 1 | Page 2 | Page 3

or:

Code
[Previous] [Next]

you can create your own pagination logic.


Step-by-Step Custom Pagination

Step 1: Create Pagination Variables

On the screen's OnVisible property:

Code
Set(varPageNumber, 1);
Set(varPageSize, 25);

Here:

  • varPageNumber stores the current page.

  • varPageSize defines how many records appear on each page.

For example:

Code
varPageNumber = 1
varPageSize   = 25

means:

Display the first 25 records.


For a small dataset, the Gallery Items property can use:

Code
FirstN(
    Skip(
        Customers,
        (varPageNumber - 1) * varPageSize
    ),
    varPageSize
)

The formula works like this:

Page 1

Code
Skip = (1 - 1) × 25
     = 0

Show = 25 records

Result:

Code
Records 1–25

Page 2

Code
Skip = (2 - 1) × 25
     = 25

Show = 25 records

Result:

Code
Records 26–50

Page 3

Code
Skip = (3 - 1) × 25
     = 50

Result:

Code
Records 51–75

Step 3: Add a Next Button

Set the Next button's OnSelect property:

Code
Set(
    varPageNumber,
    varPageNumber + 1
)

When the user clicks Next:

Code
Page 1
   ↓
Page 2
   ↓
Page 3
   ↓
Page 4

The Gallery automatically displays the corresponding records.

Step 4: Add a Previous Button

Set the Previous button's OnSelect:

Code
Set(
    varPageNumber,
    Max(
        1,
        varPageNumber - 1
    )
)

The Max() function ensures that the page number never becomes less than 1.

Step 5: Display the Page Number

Add a Label and use:

Code
"Page " & varPageNumber

The user will see:

Code
Page 1

or:

Code
Page 5

Step 6: Disable Previous on Page 1

Set the Previous button's DisplayMode:

Code
If(
    varPageNumber = 1,
    DisplayMode.Disabled,
    DisplayMode.Edit
)

This prevents users from clicking Previous when they are already on the first page.

Pagination can also be combined with a search box.

For example:

Code
FirstN(
    Skip(
        Filter(
            Customers,
            StartsWith(
                CustomerName,
                txtSearch.Text
            )
        ),
        (varPageNumber - 1) * varPageSize
    ),
    varPageSize
)

The basic flow becomes:

Code
Search
   ↓
Filter
   ↓
Pagination
   ↓
Gallery

For example, if the user searches:

Code
"ABC"

the app first filters the customers and then displays the required page.


Adding Sorting

You can also sort the filtered data.

Example:

Code
SortByColumns(
    Filter(
        Customers,
        StartsWith(
            CustomerName,
            txtSearch.Text
        )
    ),
    "CustomerName",
    SortOrder.Ascending
)

This provides a better user experience:

Code
Search → Filter → Sort → Display

Important: Delegation

This is the most important consideration when implementing pagination.

The following formula is easy to understand:

Code
FirstN(
    Skip(
        Customers,
        (varPageNumber - 1) * varPageSize
    ),
    varPageSize
)

But Skip() and FirstN() are not suitable for large remote datasets as a general scalability strategy, because they aren't generally delegable.

For example:

Code
500 records       → Small
2,000 records     → Be careful
10,000 records    → Delegation becomes important
100,000+ records  → Use a scalable approach

A delegation warning can mean that Power Apps is processing only a limited number of records locally instead of querying the complete remote dataset.

Therefore, don't assume that a formula that works with 100 records will work correctly with 100,000 records.

Recommended Approach for Large Data

For large Dataverse, SharePoint, SQL, or other remote datasets, prefer:

Code
Data Source
     ↓
Delegable Filter
     ↓
Delegable Sort
     ↓
Small Data Result
     ↓
Gallery

When explicit page navigation is required for very large datasets, consider keyset/cursor pagination.

Instead of saying:

Skip the first 5,000 records.

you use a unique key:

Give me the next 25 records after the last record I received.

For example:

Code
Page 1
CustomerId > 0
       ↓
Records 1–25
       ↓
LastId = 25

Page 2
CustomerId > 25
       ↓
Records 26–50
       ↓
LastId = 50

This is much more scalable than repeatedly skipping an increasing number of records.

Pagination Decision Guide

Requirement

Recommended Approach

Small dataset

Simple custom pagination

Normal Gallery

Direct data-source binding

Search

Delegable Filter()

Sorting

Delegable SortByColumns()

Page numbers

Custom pagination

Thousands of records

Delegation-focused design

Very large dataset

Keyset/cursor pagination

Enterprise application

Delegation + server-side filtering

Best Practices

1. Don't load everything into a collection

Avoid unnecessarily doing:

Code
ClearCollect(
    colCustomers,
    Customers
)

for a very large dataset.

2. Use delegation

Let the data source perform filtering and sorting whenever possible.

3. Keep the data payload small

Only retrieve the data the user actually needs.

4. Use a unique key for large datasets

For cursor pagination, use a reliable key such as:

Code
CustomerId
SequenceNumber
CreatedDate + ID

5. Always check delegation warnings

Test your app with realistic data volumes, not just a few sample records.


Final Example

A simple pagination screen can look like:

Code
┌─────────────────────────────────────────┐
│           Customer List                 │
│                                         │
│ Search: [____________________]          │
│                                         │
│ Customer        City       Status       │
│ ─────────────────────────────────────── │
│ ABC Ltd         Mumbai     Active       │
│ XYZ Ltd         Pune       Active       │
│ ABC Corp        Delhi      Inactive     │
│ ...                                     │
│                                         │
│ [Previous]       Page 1       [Next]    │
└─────────────────────────────────────────┘

The basic flow is:

Code
              Customer Data
                    ↓
              Search / Filter
                    ↓
              Sort (Optional)
                    ↓
               Pagination
                    ↓
                 Gallery
                    ↓
          Previous ← Page → Next

Conclusion

Pagination is a useful technique for making large datasets easier to navigate in Power Apps Canvas Apps.

For small datasets, a simple Skip() + FirstN() approach is easy to implement.

For large datasets, don't rely on client-side pagination. Instead, build the solution around delegation, server-side filtering, small data payloads, and keyset/cursor pagination where necessary.

The key rule is simple:

Don't bring a large dataset into Power Apps just to paginate it. Let the data source do the heavy work whenever possible.