finds.dev← search

// the find

duffelhq/paginator

★ 822 · Elixir · MIT · updated Apr 2025

Cursor-based pagination for Elixir Ecto

Paginator adds keyset (cursor-based) pagination to Ecto repos via a single `use Paginator` macro. It solves the real problem with offset pagination — inconsistent results and O(N) database scans — and is maintained by Duffel, who clearly use it in production. Aimed at Phoenix/Ecto apps that serve feeds, timelines, or any list that scrolls.

The cursor encoding handles multi-column sort keys correctly, including nulls-first/last variants which most hand-rolled implementations get wrong. Dynamic expression support via `fetch_cursor_value_fun` lets you paginate on computed columns like `ts_rank` without hacks. The security check against executable terms in cursor params is a nice production detail. Integration with Repo via `use Paginator` means no extra abstractions — it's just `Repo.paginate/2`.

Postgres-only and they say so, but it's a hard limitation if your team ever moves to MySQL or SQLite. The `total_count` option fires a separate COUNT(*) query with no caching — easy footgun for large tables behind a public API. Dynamic expression cursor fields require re-executing the expression per row to fetch the cursor value, which is a raw query inside a callback — ugly and easy to mess up. No built-in way to page to an arbitrary position; you must walk forward from the start, which frustrates use cases that want deep linking to a specific result page.

View on GitHub →

// want more like this?

We dig through GitHub every week and send a few repos picked for what you actually care about — each with an honest take like this one.

Get finds in your inbox → Search again →