Struggling to efficiently page a large dataset

Struggling with a strategy to efficiently page through millions of records (not all at once) without having to use skip() due to poor performance of skip() the deeper into a query we get. We have a date field that we sort by in descending order and I have indexes setup to answer the query and the sort. The problem is that the collection could have many records with the exact same timestamp so I can’t “just” get the next page by a match where I match timestamp is $lt the last value on the current page (sorting in reverse chronological order). I can’t simply use the addition of _id to the sort because records inserted “later” may have timestamps that are “earlier”. I sort of need the equivalent of saying where date is $lte date of last record on the current page and _id gt last record on current page’s _id only if timestamp is the same, otherwise _id can be anything. Hopefully my issue makes sense.

If I just use the date by itself then I would have to sacrifice having any soft of consistent page size because what would happen if I had a page size of 50 but there were 75 records with the same timestamp. I would either not be able to advance the page at all OR I would lose visibility of any records after the first 50 for that timestamp. What I think I really need and I’m not sure if MongoDB has a way for me to do this, is a composite sort value where I could have the combo of { timestamp: <datetime>, _id: <objectid> } where the 2nd part is only considered if the first is the same.

In other words, if I reduce timestamp and _id to integers just to make this easier to type, given the following simplified documents:

{ timestamp: 1, _id: 1 }
{ timestamp: 2, _id: 3 }
{ timestamp: 2, _id: 4 }
{ timestamp: 2, _id: 5 }
{ timestamp: 3, _id: 6 }
{ timestamp: 4, _id: 2 }

I can obviously easily sort this by { timestamp: -1, _id: 1 } (using an index that supports this) and get:

{ timestamp: 4, _id: 2 }
{ timestamp: 3, _id: 6 }
{ timestamp: 2, _id: 3 }
{ timestamp: 2, _id: 4 }
{ timestamp: 2, _id: 5 }
{ timestamp: 1, _id: 1 }

BUT, if the page ended with { timestamp: 2, _id: 3 }, I don’t know how to query for the next page because if I just did a match on { timestamp: { "$lte": 2 }, "_id": { "$gt": 3 } } it wouldn’t end up matching { timestamp: 1, _id: 1 } because _id would be less than 3.

NOTE: There are other fields involved in the queries match and index that I have left off for brevity.