sqlakeyset
offset-free paging for sqlalchemy
Decision gist · record as of 2026-08-14
Yes. sqlakeyset solves a real performance and correctness problem in paginated queries—offset pagination degrades as you go deeper and can lose or duplicate rows in changing datasets. The library is actively maintained, has no known vulnerabilities, requires only common dependencies, and supports both modern SQLAlchemy 2 and legacy ORM styles. The Unlicense places no restrictions. Install if you paginate large or frequently-changing result sets.AI-flagged interpretation of the facts on this page — verify before relying
Before you install
- Requires Python 3.9 or later; ordering columns must be NOT NULL and unique per row (include primary key at end of order clause).
- Low friction install with four lightweight runtime dependencies (packaging, python-dateutil, sqlalchemy, typing-extensions).
- Active maintenance with recent commits; last release 133 days ago.
License · maintenance · safety
Unlicense (permissive) — Unlicense (permissive) places no restrictions on use, modification, or distribution.
last release 2026-04-03 (133 days) · last repo commit 2026-04-03 · 395 stars
0 known vulnerabilities (OSV.dev, 2026-08-14) · 1,295,563 downloads/mo, #4,094 on PyPI
Alternatives
Verify before relying
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session
from sqlakeyset import select_page
engine = create_engine('postgresql:///books')
with Session(engine) as s:
q = select(Book).order_by(Book.author, Book.title, Book.id)
page1 = select_page(s, q, per_page=20)
next_page = page1.paging.next
page2 = select_page(s, q, per_page=20, page=next_page)- Whether keyset paging performance remains constant at very large offsets compared to offset-based queries.
- Compatibility with databases beyond PostgreSQL, MariaDB/MySQL, and SQLite mentioned in the description.
- Whether async support (sqlakeyset.asyncio) is feature-complete relative to synchronous API.
What it is and what it does
sqlakeyset replaces SQL OFFSET-based pagination with keyset (cursor) pagination for SQLAlchemy. Traditional offset queries slow down as you page deeper into results and can skip or repeat rows if data changes between requests; keyset paging avoids both problems by bookmarking your position using the actual row values and fetching only rows after that bookmark. The library works with both SQLAlchemy ORM and Core, supports SQLAlchemy 2 with full type hints, and includes async support via sqlakeyset.asyncio.
You order your query normally, then call select_page() or get_page() to fetch a page and receive a Page object (a list with attached paging metadata). The metadata includes next and previous markers—tuples of the row's key values—which you serialize to bookmarks (strings) for passing around URLs or APIs. On the next request, you pass that bookmark back to fetch the next or previous page. The library handles all the WHERE clause manipulation and ordering reversal internally.
Use it for
- Paginating large result sets in web applications without performance degradation as users navigate deeper into results.
- Implementing cursor-based API pagination where clients receive opaque bookmark strings to request next/previous pages.
- Handling frequently-changing datasets where offset-based pagination risks skipping or repeating rows between page requests.
- Building async database applications with keyset pagination using AsyncSession.
- Sorting by nullable columns by wrapping them with coalesce() to ensure consistent, non-null ordering keys.
Worth the install?
AI-flagged interpretation of the facts on this page. Verify before relying on it.
Yes.
sqlakeyset solves a real performance and correctness problem in paginated queries—offset pagination degrades as you go deeper and can lose or duplicate rows in changing datasets. The library is actively maintained, has no known vulnerabilities, requires only common dependencies, and supports both modern SQLAlchemy 2 and legacy ORM styles. The Unlicense places no restrictions. Install if you paginate large or frequently-changing result sets.
Install
sqlakeyset on PyPI
Before you install
Low friction install with four lightweight runtime dependencies (packaging, python-dateutil, sqlalchemy, typing-extensions). Active maintenance with recent commits; last release 133 days ago.
Requires Python 3.9 or later; ordering columns must be NOT NULL and unique per row (include primary key at end of order clause).
License in practice
Unlicense (permissive) places no restrictions on use, modification, or distribution.
Quickstart
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session
from sqlakeyset import select_page
engine = create_engine('postgresql:///books')
with Session(engine) as s:
q = select(Book).order_by(Book.author, Book.title, Book.id)
page1 = select_page(s, q, per_page=20)
next_page = page1.paging.next
page2 = select_page(s, q, per_page=20, page=next_page)
Verify before relying
- Whether keyset paging performance remains constant at very large offsets compared to offset-based queries.
- Compatibility with databases beyond PostgreSQL, MariaDB/MySQL, and SQLite mentioned in the description.
- Whether async support (sqlakeyset.asyncio) is feature-complete relative to synchronous API.
Package facts
| License | Unlicense permissive |
| Python support | Supports the current Python release >=3.9 |
| Install friction | Low. Pure-Python wheel |
| Runtime dependencies | 4 packagespackagingpython-dateutilsqlalchemytyping-extensions |
| Maintenance | Actively maintained 133 days since the last release |
| Last repo commit | |
| First released | |
| Downloads | 1,295,563 / month, #4,094 on PyPI 30-day window, as of 2026-08-14 |
| Known vulnerabilities | None known OSV.dev, checked 2026-08-14 |
Evidence: sqlakeyset-2.0.1775222100-py3-none-any.whl
Tags
Let your AI agent find packages like this
Example. Real query, live index.
You found this page by searching. An agent finds it by wishing: SkillFed indexes 14,416 PyPI packages by what they can do, searchable in plain language.
wish › “keyset paging sqlalchemy”
- sqlakeysetImplements keyset-based paging for SQLAlchemy queries, replacing…
- autopageAutomatically pipes terminal output to a pager like `less` when…
- django-cursor-paginationImplements cursor-based pagination for Django querysets, allowing…
Give your agent the search over MCP, or paste the wish link into any chat.
More Database packages
psycopg2-binary is a PostgreSQL database adapter for Python that implements the DB API 2.0 specification, enabling Python applications to connect to and query PostgreSQL databases with thread-safe concurrent operations.
Python client library for connecting to and executing commands against Redis key-value stores, supporting both synchronous and asynchronous operations.
Install it if your application needs to interact with Redis; the only prerequisite is a running Redis server instance.
YDB Python SDK is the official client library for connecting to and querying YDB databases from Python applications.
Install it if you need to connect Python applications to YDB databases.
Connects Python applications to Snowflake data warehouses using the DB API 2.0 specification, enabling SQL queries, data transfers, and warehouse operations.
sqlparse tokenizes SQL text into a tree of statements, clauses, and expressions, and provides functions to split scripts, format queries, and inspect parsed tokens without validating dialect or syntax.
Install it if you need to manipulate, format, or analyze SQL text programmatically.
Provides base adapter protocols and shared functionality that database adapters use to integrate with dbt-core, handling connections, dialect translation, relation caching, and core interface management.
See also fastcrud · django-cursor-pagination · sqlalchemy-jdbcapi · SQLAlchemy · sqlalchemy-solr · sqlalchemy-spanner · elasticsearch-dbapi · casbin-async-sqlalchemy-adapter · sqlalchemy-cockroachdb · fastapi-pagination