Competitive Analysis
pypaginate v0.2.0 vs the Python pagination ecosystem – an honest, benchmark-backed assessment.
The Ecosystem
Library |
Stars |
Focus |
Backends |
|---|---|---|---|
1,635 |
Pagination |
19 (SA, Beanie, Tortoise…) |
|
302 |
SA filtering |
SQLAlchemy, MongoEngine |
|
– |
Keyset pagination |
SQLAlchemy |
|
80 |
Offset pagination |
SQLAlchemy |
|
– |
In-memory pagination |
Any sequence |
|
pypaginate |
– |
All-in-one |
Memory, SQLAlchemy, FastAPI |
Feature Comparison
Feature |
pypaginate |
fastapi-pagination |
fastapi-filter |
paginate-lib |
|---|---|---|---|---|
Offset pagination |
yes |
yes |
no |
yes |
Cursor/keyset pagination |
yes |
yes |
no |
no |
In-memory filtering (20 ops) |
yes |
no |
no |
no |
In-memory sorting (null-aware) |
yes |
no |
no |
no |
In-memory search (fuzzy+Unicode) |
yes |
no |
no |
no |
SA filtering (WHERE) |
yes |
no |
yes |
no |
SA sorting (ORDER BY) |
yes |
no |
no |
no |
SA search (LIKE/ILIKE) |
yes |
no |
no |
no |
Full pipeline (filter+sort+search+paginate) |
yes |
no |
no |
no |
Nested filter groups (And/Or) |
yes |
no |
partial |
no |
Sync + async auto-detection |
yes |
yes |
no |
no |
FastAPI integration |
yes |
yes |
yes |
no |
msgspec fast pages |
yes |
no |
no |
no |
Type-safe (Elysia-style inference) |
yes |
partial |
no |
no |
|
yes |
yes |
no |
no |
pypaginate is the only library that does filter + sort + search + paginate in one call.
Performance Benchmarks (10K items)
All benchmarks run on the same machine, same data, same operations. Competitors that cannot filter/sort use raw Python for those steps plus their own pagination.
Paginate Only (all libraries can do this)
Rank |
Library |
Median |
vs #1 |
|---|---|---|---|
#1 |
pypaginate |
1.2 us |
– |
#2 |
paginate-lib |
1.4 us |
1.2x |
#3 |
fastapi-pagination |
44.5 us |
37.6x |
SA Paginate Sync (COUNT + OFFSET/LIMIT on same SQLite DB)
Rank |
Library |
Median |
vs #1 |
|---|---|---|---|
#1 |
pypaginate sync |
330 us |
– |
#2 |
sqlakeyset |
379 us |
1.1x |
#3 |
sqlalchemy-pagination |
487 us |
1.5x |
#4 |
fastapi-pagination SA |
572 us |
1.7x |
Full Pipeline: filter + sort + paginate
All libraries do the same work. Competitors use raw Python for filter+sort, then their paginate.
Rank |
Library |
Median |
How filter+sort is done |
|---|---|---|---|
#1 |
paginate-lib |
682 us |
Raw Python list comp + sorted() |
#2 |
fastapi-pagination |
756 us |
Raw Python list comp + sorted() |
#3 |
pypaginate |
2.50 ms |
Built-in compiled pipeline |
Why the gap? Competitors use raw Python list comprehension + sorted() for filter+sort – zero abstraction overhead. pypaginate uses compiled predicates + null-aware sorting – features that have a cost in CPython.
SA Filter (WHERE clause + pagination)
Rank |
Library |
Median |
Note |
|---|---|---|---|
#1 |
fastapi-filter |
320 us |
Builds WHERE clause only (no COUNT/OFFSET) |
#2 |
pypaginate SA |
816 us |
Full pipeline (WHERE + COUNT + OFFSET/LIMIT) |
Why the gap? fastapi-filter only builds the SQL WHERE clause – no database execution. pypaginate does the full pipeline: WHERE + COUNT + OFFSET/LIMIT.
Overhead Breakdown (10K items)
Paginate + serialize adds near-zero overhead. The HTTP layer dominates.
Step |
Filter |
Sort |
Search |
Paginate |
|---|---|---|---|---|
Ops only |
928 us |
1.73 ms |
8.98 ms |
1.2 us |
+ Paginate |
942 us (+14us) |
1.71 ms (+0) |
7.76 ms (+0) |
– |
+ Serialize |
918 us (+0) |
1.78 ms (+71us) |
8.94 ms (+0) |
3.9 us (+2.7us) |
+ Full HTTP |
11.51 ms (+10.6ms) |
10.43 ms (+8.7ms) |
18.69 ms (+9.8ms) |
8.91 ms (+8.9ms) |
Key finding: Paginate and serialize add essentially zero overhead. The HTTP layer (FastAPI request/response encoding) adds roughly 9ms constant – this is FastAPI’s cost, not pypaginate’s.
DX Comparison: Endpoint Code
With fastapi-pagination + fastapi-filter (2 libraries)
from fastapi_pagination import Page, add_pagination, paginate
from fastapi_filter import FilterDepends
from fastapi_filter.contrib.sqlalchemy import Filter
app = FastAPI()
add_pagination(app)
class UserFilter(Filter):
name__ilike: str | None = None
age__gte: int | None = None
class Constants(Filter.Constants):
model = User
@app.get("/users", response_model=Page[UserSchema])
async def get_users(
user_filter: UserFilter = FilterDepends(UserFilter),
):
query = user_filter.filter(select(User))
return await paginate(query)
With pypaginate v0.2.0 (1 library)
from pypaginate import paginate, OffsetParams, FilterSpec
from pypaginate.adapters.fastapi import OffsetDep
from pypaginate.adapters.sqlalchemy import SQLAlchemyBackend, SQLAlchemyFilterBackend
from pypaginate.engine.pipeline import AsyncPipeline
from pypaginate.engine.paginator import AsyncPaginator
@app.get("/users")
async def get_users(
params: OffsetDep,
session: AsyncSession = Depends(get_session),
name: str | None = Query(None),
min_age: int | None = Query(None),
):
filters = []
if name:
filters.append(FilterSpec(field="name", operator="contains", value=name))
if min_age:
filters.append(FilterSpec(field="age", operator="gte", value=min_age))
backend = SQLAlchemyBackend(session)
pipeline = AsyncPipeline(
AsyncPaginator(backend),
filter_backend=SQLAlchemyFilterBackend(),
)
return await pipeline.execute(select(User), params, filters=filters)
Comparison
Aspect |
fastapi-pagination + filter |
pypaginate |
|---|---|---|
Libraries needed |
2 |
1 |
Filter declaration |
Declarative (class) |
Declarative ( |
Sorting |
Built into filter class |
|
Search |
Basic (ilike only) |
|
Type safety |
Partial (string operators) |
Full (Literal types, protocols) |
In-memory support |
No |
Yes (same API) |
Auto OpenAPI for filters |
Yes |
Yes ( |
Nested filter groups |
No |
Yes (And/Or builders) |
Where pypaginate Wins
Performance: #1 for pagination (1.2us vs paginate-lib 1.4us vs fp 44.5us).
SA Performance: Faster than sqlakeyset and raw SA pagination (330us vs 379us).
Unified library: Filter + sort + search + paginate in one
pip install.Search: Only library with fuzzy matching, Unicode normalization, accent removal.
Type safety:
mypy --strict, Elysia-style type inference, Literal operator types.Architecture: Protocol-based backends, compile-once strategy,
__slots__everywhere.msgspec acceleration: Near-zero page construction with
pypaginate[fast].Nested filters:
And()/Or()groups up to 5 levels deep.
Where pypaginate Lags
DB backends: SQLAlchemy only (competitors support 19 backends).
Full pipeline speed: Behind competitors that use raw Python for filter+sort.
Zero-config middleware: No
add_pagination(app)– explicit setup required.
Roadmap
Version |
Focus |
Status |
|---|---|---|
v0.2.0 |
Hexagonal architecture, protocol backends, unified paginate(), FilterDep, SortDep, SearchDep |
Done |
v0.3.0 |
JSON Logic parser, |
Planned |
v0.4.0 |
Multi-backend (Beanie, Tortoise), additional ORM support |
Planned |
v1.0.0 |
Rust core extension for 10x filter/search speed |
Planned |