Get your case straight. First, a proper table definition. We need a PK or similar to break ties unambiguously: ~~~pgsql CREATE TABLE users ( user_id int PRIMARY KEY , update_time timestamptz NOT NULL , about_me text NOT NULL ); ~~~ The column `update_time` is type `timestamptz`. Keep working with `timestamptz`, and don't mix with `timestamp`. Next, sample rows to exhibit possible problems: ~~~pgsql INSERT INTO users VALUES (1, '2023-04-06 19:59:56.771388 +00:00', 'Hello! How are you?') , (3, '2023-04-02 03:31:09.833925 +00:00', 'Hello!!!') , (2, '2023-04-06 00:36:26.822102 +00:00', 'Hello!') , (4, '2023-04-05 19:16:20.968274 +00:00', 'Hey!') , (5, '2023-04-02 03:31:09.833925 +00:00', 'Same len') , (7, '2023-05-02 03:31:09.833925 +00:00', 'Later!!!') , (6, '2023-03-02 03:31:09.833925 +00:00', 'Earlier!') ; ~~~ Proper base query: ~~~pgsql SELECT user_id, update_time, about_me FROM users u ORDER BY date_bin('14 days', update_time, '2023-04-07 23:11:56+0') DESC , length(about_me) DESC , user_id DESC; -- ! ~~~ `'2023-04-07 23:11:56+0'` being your arbitrary (but constant!) time anchor. Notably, you added `user_id` as 3rd expression to `ORDER BY` to break ties. That's good. But if you want to keep using [***Row Constructor Comparison***][1], all 3 expressions must share the **same sort direction**. All `ASCENDING` or all `DESCENDING`. (Else it gets more complex and expensive.) See: - [SQL syntax term for 'WHERE (col1, col2) < (val1, val2)'][2] - [How to form a WHERE condition matching multiple ORDER BY items?][3] Also, add `user_id` to the `SELECT` list. It's essential for your pagination. Then, to get the 1st page with an example page size of ***3***: ~~~pgsql SELECT user_id, update_time, about_me FROM users u ORDER BY date_bin('14 days', update_time, '2023-04-07 23:11:56+0') DESC , length(about_me) DESC , user_id DESC LIMIT 3; ~~~ 2nd page: ~~~pgsql SELECT user_id, update_time, about_me FROM users u WHERE (date_bin('14 days', update_time, '2023-04-07 23:11:56+0'), length(about_me), user_id) < ('2023-03-25 00:11:56+01', 8, 5) ORDER BY date_bin('14 days', update_time, '2023-04-07 23:11:56+0') DESC , length(about_me) DESC , user_id DESC LIMIT 3; ~~~ [fiddle](https://dbfiddle.uk/ON5GXBHt) `('2023-03-25 00:11:56+01', 8, 5)` being derived from the last row of the first page. `'2023-03-25 00:11:56+01'` is the result of the `date_bin()` expression. You might add it to the `SELECT` list for simplicity. (I added it in the fiddle.) Since your `date_bin()` expression uses an arbitrary time anchor (and interval?), using an index is sophisticated, but still possible. Work with the lower / upper bounds of possible `date_bin()` values ... These two `timestamptz` values are exactly the same: ~~~none '2023-03-24 23:11:56+00' '2023-03-25 00:11:56+01' ~~~ The *display* depends on the `timezone` setting of your session, the *value* is the same. Basics: - [Ignoring time zones altogether in Rails and PostgreSQL][4] [1]: https://www.postgresql.org/docs/current/functions-comparisons.html#ROW-WISE-COMPARISON [2]: https://stackoverflow.com/a/32982895/939860 [3]: https://stackoverflow.com/a/56009745/939860 [4]: https://stackoverflow.com/a/9576170/939860