Timestamp ordering and cursor pagination with 13-digit Unix timestamps
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 8.7k
- Forks
- 374
- Avg merge
- 11d 16h
- Merged PRs (30d)
- 1
Description
im having trouble implementing cursor-based pagination with timestamp ordering in an Apollo Server application using postgres.js.
My posts table has a created_at column of type timestamp. I want to paginate posts using after and before cursors and order the results by created_at.
The after and before values are received as strings containing 13-digit Unix timestamps in milliseconds, for example:
1787758015041
However, the query below does not behave as expected. Depending on the parameters, it either returns no results or returns the same results instead of correctly paginating/sorting by created_at.
async getPosts(
first?: number | null,
after?: string | null,
last?: number | null,
before?: string | null
) {
try {
const result = await this.dbConnection`
select
content, created_at, creator, detected_language, id, is_suspended, response_root_post, type
from posts
where is_suspended = false and type = 'public'
${after ? this.dbConnection`and created_at > to_timestamp(${after})` : this.dbConnection``}
${before ? this.dbConnection`and created_at < to_timestamp(${before})` : this.dbConnection``}
order by created_at ${last ?? before ? this.dbConnection`desc` : this.dbConnection`asc`}
limit ${first ?? last ?? 10}
`;
return result;
} catch (error) {
throw new Error(this.dictionary.errors.retrievePosts);
}
}
I have also tried passing the value explicitly as a number:
to_timestamp(${Number(after)})
and:
to_timestamp(${after})
Neither approach produced the expected pagination/order behavior.
I suspect the main issue may be related to the fact that to_timestamp() expects Unix time in seconds, while my cursors contain Unix time in milliseconds, but I'm not sure what the correct approach should be when using postgres.js.
What I would like to know
Could someone please explain the recommended way to implement this?
Specifically:
How should I convert a 13-digit Unix timestamp in milliseconds to a PostgreSQL timestamp for comparison?
What is the correct way to implement after / before cursor pagination with created_at?
Is there anything incorrect about the ORDER BY expression or the way I'm using postgres.js to dynamically specify ASC / DESC?
Should I use created_at alone as the cursor, or should I include id as a secondary cursor to handle posts with identical timestamps?
Any example query or recommended implementation for postgres.js would be greatly appreciated.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the posted getPosts query and the PostgreSQL to_timestamp and cursor-pagination behavior it relies on; no repository file or test is identified. Determine whether the issue reflects postgres.js behavior or application-level SQL usage, then document the supported timestamp conversion, ordering, cursor semantics, and tie-breaking expectations with a reproducible example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nodejs, postgresql
- Domain
- backend-api-design, databases
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100