The downside is that OFFSET is slow if you have a lot of items, like on a forum.
At which point you could assign each post in a topic an indexed `position` column that always increases from 0 within that topic, which lets you jump to arbitrary pages and parameterize perPage.
fromPos = (page - 1) * perPage
SELECT *
FROM posts
WHERE topic_id = $1
AND position >= fromPos
AND position < fromPos + perPage
ORDER BY id
For simpler needs, your "Next" button could load items that come after the last ID on the current page but with a LIMIT.
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
<a href="/items?afterId={{ items[items.length - 1].id }}">Next</a>
SELECT *
FROM items
WHERE id > $afterId
LIMIT $perPage
At which point you could assign each post in a topic an indexed `position` column that always increases from 0 within that topic, which lets you jump to arbitrary pages and parameterize perPage.
For simpler needs, your "Next" button could load items that come after the last ID on the current page but with a LIMIT. That's fast and really easy.