<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MantaHQ</title>
    <description>The latest articles on DEV Community by MantaHQ (@mantahq).</description>
    <link>https://dev.to/mantahq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3765160%2Fd31c9af5-6be7-459f-9bad-25b90c076fe0.png</url>
      <title>DEV Community: MantaHQ</title>
      <link>https://dev.to/mantahq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mantahq"/>
    <language>en</language>
    <item>
      <title>Implementing pagination with PostgreSQL and the MantaHQ SDK</title>
      <dc:creator>MantaHQ</dc:creator>
      <pubDate>Wed, 18 Feb 2026 10:40:17 +0000</pubDate>
      <link>https://dev.to/mantahq/implementing-pagination-with-postgresql-and-the-mantahq-sdk-1nnn</link>
      <guid>https://dev.to/mantahq/implementing-pagination-with-postgresql-and-the-mantahq-sdk-1nnn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbybuz7d67cytfdlf6xlh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbybuz7d67cytfdlf6xlh.png" alt="Learn how to implement efficient pagination using PostgreSQL and the MantaHQ SDK. Compare traditional SQL pagination with the SDK approach, reduce backend complexity, and fetch large datasets effortlessly in React applications."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Pagination improves performance and usability when applications display large datasets. Pagination limits the number of records returned in each request and reduces rendering overhead in the browser.&lt;/p&gt;

&lt;p&gt;This article explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how pagination works in PostgreSQL&lt;/li&gt;
&lt;li&gt;the hidden complexity of traditional pagination architectures&lt;/li&gt;
&lt;li&gt;how the MantaHQ SDK simplifies pagination across PostgreSQL databases and MantaHQ internal tables&lt;/li&gt;
&lt;li&gt;when developers should and should not use the MantaHQ SDK&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why pagination exists
&lt;/h2&gt;

&lt;p&gt;Applications often need to display thousands or millions of records. Loading all records at once increases query time, memory usage, and network latency. Pagination solves these problems by dividing results into smaller segments.&lt;/p&gt;

&lt;p&gt;Pagination provides the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reduces database query load&lt;/li&gt;
&lt;li&gt;reduces data transfer size&lt;/li&gt;
&lt;li&gt;improves browser rendering performance&lt;/li&gt;
&lt;li&gt;improves user navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most applications use one of the following pagination strategies:&lt;/p&gt;

&lt;h3&gt;
  
  
  Page-based pagination
&lt;/h3&gt;

&lt;p&gt;Page-based pagination retrieves results by page number. The application calculates which rows to skip and which rows to return.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor-based pagination
&lt;/h3&gt;

&lt;p&gt;Cursor-based pagination retrieves results using a unique record identifier. Cursor pagination performs better when datasets grow large. This article focuses on page-based pagination because page-based pagination remains the most common implementation.&lt;/p&gt;




&lt;h2&gt;
  
  
  How pagination works in traditional applications
&lt;/h2&gt;

&lt;p&gt;Traditional pagination requires multiple infrastructure layers. The following architecture shows a typical request flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7703vo9hoxyrc8f0fm0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7703vo9hoxyrc8f0fm0.png" alt="A draw.io diagram showing the architecture of a traditional typical request flow in applications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each layer performs a specific responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The browser requests a page of results.&lt;/li&gt;
&lt;li&gt;The backend validates permissions and calculates pagination values.&lt;/li&gt;
&lt;li&gt;PostgreSQL executes pagination queries.&lt;/li&gt;
&lt;li&gt;The backend returns pagination metadata and result records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers must build and maintain a backend endpoint for each dataset that supports pagination. This backend layer often introduces most of the complexity in pagination implementations.&lt;/p&gt;




&lt;h2&gt;
  
  
  The tradeoffs behind traditional pagination
&lt;/h2&gt;

&lt;p&gt;Pagination often appears simple, but supporting pagination across database queries, backend services, and frontend state management requires significant code.&lt;/p&gt;

&lt;h3&gt;
  
  
  PostgreSQL query example
&lt;/h3&gt;

&lt;p&gt;The following query retrieves the second page of users when each page contains ten records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PostgreSQL query requires the developer to calculate the offset manually using the following formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(page_number - 1) * page_size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pagination also requires a second query to calculate the total number of records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How pagination is handled on the backend
&lt;/h3&gt;

&lt;p&gt;To support pagination, the backend endpoint usually handles these tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validates query parameters&lt;/li&gt;
&lt;li&gt;calculates offsets&lt;/li&gt;
&lt;li&gt;executes pagination queries&lt;/li&gt;
&lt;li&gt;calculates page counts&lt;/li&gt;
&lt;li&gt;returns structured pagination metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pagination endpoints often require more than sixty lines of backend code after developers implement validation, access control, and error handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  How pagination is handled on the client side
&lt;/h3&gt;

&lt;p&gt;To fetch, display, and navigate paginated records, the frontend must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;store current page state&lt;/li&gt;
&lt;li&gt;send page parameters to the backend&lt;/li&gt;
&lt;li&gt;update pagination controls&lt;/li&gt;
&lt;li&gt;manage loading and error states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing frontend pagination often adds forty or more lines of state management and UI logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traditional pagination summary
&lt;/h3&gt;

&lt;p&gt;Traditional pagination often requires:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Typical Complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL queries&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend pagination logic&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend pagination state&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Developers must maintain backend, frontend, and database logic for each dataset that requires pagination.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pagination using the MantaHQ SDK
&lt;/h2&gt;

&lt;p&gt;The MantaHQ SDK reduces pagination complexity by acting as a unified data access layer. The MantaHQ SDK connects directly to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL databases&lt;/li&gt;
&lt;li&gt;MantaHQ internal data tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers use a single syntax for pagination regardless of the data source.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the MantaHQ SDK changes the workflow
&lt;/h3&gt;

&lt;p&gt;The MantaHQ SDK simplifies pagination by providing a single data access layer. It connects directly to both your PostgreSQL database and internal Manta tables, eliminating the need for separate backend endpoints and manual offset calculations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calculates pagination offsets&lt;/li&gt;
&lt;li&gt;retrieves total record counts&lt;/li&gt;
&lt;li&gt;returns structured pagination metadata&lt;/li&gt;
&lt;li&gt;enforces database access controls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MantaHQ SDK reduces pagination implementation from three layers to two layers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng1adke3l7tr69wn73tp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng1adke3l7tr69wn73tp.png" alt="A draw.io diagram showing the architecture of a request flow in applications whose data is managed with mantahq sdk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching paginated data with the Manta SDK
&lt;/h3&gt;

&lt;p&gt;This example demonstrates how to implement pagination in a job board application using React and the MantaHQ SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MantaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mantahq-sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_MANTAHQ_API_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MantaClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sdkKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;JobList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setJobs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTotalPages&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentPage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchJobs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;manta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchAllRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;company&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nf"&gt;setJobs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setTotalPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;fetchJobs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; - &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCurrentPage&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Previous
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCurrentPage&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Next
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;JobList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  What this code is doing
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reactive fetching with&lt;/strong&gt; &lt;code&gt;useEffect&lt;/code&gt;: The component monitors &lt;code&gt;currentPage&lt;/code&gt;. Each time the page changes, it triggers an SDK call to fetch the corresponding dataset segment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic offset and limit calculation:&lt;/strong&gt; The SDK handles &lt;code&gt;LIMIT&lt;/code&gt; and &lt;code&gt;OFFSET&lt;/code&gt; internally based on the &lt;code&gt;list&lt;/code&gt; parameter. Developers don’t need to manually compute SQL pagination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination metadata provided:&lt;/strong&gt; The response includes &lt;code&gt;data.meta.totalPages&lt;/code&gt;. The component uses this to enable or disable “Next” and “Previous” buttons accurately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal state management:&lt;/strong&gt; Frontend only tracks &lt;code&gt;jobs&lt;/code&gt;, &lt;code&gt;currentPage&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt;. The SDK abstracts database querying and counting logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified database interface:&lt;/strong&gt; The same SDK call works for MantaHQ internal tables or external PostgreSQL databases, eliminating backend boilerplate and reducing integration complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SDK pagination workflow
&lt;/h3&gt;

&lt;p&gt;The SDK accepts pagination parameters and handles database pagination internally. It eliminates manual offset calculations and the need for separate count queries.&lt;/p&gt;

&lt;p&gt;The SDK also returns pagination metadata in a single response. The frontend uses this metadata to manage navigation buttons and page indicators automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Traditional pagination vs MantaHQ SDK
&lt;/h2&gt;

&lt;p&gt;The table below compares pagination implemented manually with a backend versus pagination handled using the MantaHQ SDK:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / Task&lt;/th&gt;
&lt;th&gt;Traditional Pagination&lt;/th&gt;
&lt;th&gt;MantaHQ SDK&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend endpoints needed&lt;/td&gt;
&lt;td&gt;One per dataset&lt;/td&gt;
&lt;td&gt;Not required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offset calculation&lt;/td&gt;
&lt;td&gt;Manual calculation required&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total record counting&lt;/td&gt;
&lt;td&gt;Separate SQL query needed&lt;/td&gt;
&lt;td&gt;Included in SDK response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code maintenance burden&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development time&lt;/td&gt;
&lt;td&gt;Longer&lt;/td&gt;
&lt;td&gt;Shorter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend integration&lt;/td&gt;
&lt;td&gt;Manual state &amp;amp; UI logic&lt;/td&gt;
&lt;td&gt;Automatic metadata handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Run the pagination example
&lt;/h2&gt;

&lt;p&gt;Complete a working pagination example in under fifteen minutes by following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/trevorcj/jobber/blob/main/jobs_seed.csv" rel="noopener noreferrer"&gt;Download the example dataset&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Upload the dataset to a Manta internal table or connect a PostgreSQL database.&lt;/li&gt;
&lt;li&gt;Install the MantaHQ SDK.&lt;/li&gt;
&lt;li&gt;Implement pagination using the provided example component.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Follow the MantaHQ documentation for setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.mantahq.com/databases/connections/connecting-to-external-databases" rel="noopener noreferrer"&gt;Connect your PostgreSQL database to MantaHQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mantahq.hashnode.dev/how-to-turn-a-spreadsheet-into-an-api-in-minutes" rel="noopener noreferrer"&gt;Upload a CSV to Manta internal tables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.mantahq.com/quickstart#2-technical-setup" rel="noopener noreferrer"&gt;Install the MantaHQ SDK&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Pagination is essential for scalable applications. Traditional approaches require coordinating database queries, backend APIs, and frontend state management, which increases development time and maintenance overhead.&lt;/p&gt;

&lt;p&gt;The MantaHQ SDK simplifies pagination by handling database queries, offset calculations, and metadata in a single interface. Developers can implement paginated views quickly, reduce boilerplate, and focus on building application features instead of managing infrastructure.&lt;/p&gt;




&lt;p&gt;Prefer video tutorials? Watch a step-by-step video demonstration.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/I7I2f9zO9Dg"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;For full pagination reference and advanced usage, see the &lt;a href="https://docs.mantahq.com/databases/fetching-data/fetchAllRecords/pagination" rel="noopener noreferrer"&gt;MantaHQ SDK documentation&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;By &lt;a href="https://www.linkedin.com/in/trevorcjustus/" rel="noopener noreferrer"&gt;Trevor C. Justus&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Developer Relations at MantaHQ&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>react</category>
      <category>pagination</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
