I am trying to implement a REST API endpoint that will return a set of entities, optionally filtered using various query parameters. Since the result set may be large, the endpoint will also support paging, using limit
and offset
query parameters.
The implementation seems quite straightforward, except for the scenario where qualifying entities are modified during a sequence of paged requests, in which case it is possible for certain entities to become invisible to the client.
Here's an example to demonstrate the problem.
Imagine an endpoint that returns invoice entities, optionally filtered by their payment status. We issue a request for unpaid invoices, which might naturally return 15 matches, but since each response is limited to 5 entities, the first response will contain invoices 1, 2, 3, 4 and 5.
In theory, the second request will retrieve invoices 6, 7, 8, 9 and 10 of the same result set. However, imagine that invoice 3 becomes paid before the second request is issued. This will cause the result set to shift, such that the first page of results contains invoices 1, 2, 4, 5 and 6. In this scenario, the second request will retrieve invoices 7, 8, 9, 10 and 11. The consequence is that invoice 6 never gets seen by the client.
I am not concerned about invoice 3 becoming out-of-date (on the client) before the end of the request sequence, as this a natural consequence of data that changes. However, I am concerned that the client never gets to learn of the existence of invoice 6, even though it remained unpaid throughout the entire request sequence.
It seems to me that this problem occurs because REST APIs are stateless. If the server could snapshot the result set during the first request and re-use the snapshot during subsequent requests, the problem would not occur. But since this is not the way REST works, I wonder if there is a design pattern that solves this problem?
Usally items are sorted by something, let's assume by the title. Then you can replace the offset by previousTitle
and let the API return all (up to limit
) items which come after it.