Simulator
Pagination race: why a page number breaks and a cursor does not
Paging means loading a long list in small parts. This page shows what breaks when the list changes while the reader scrolls. Change one thing, then look at what happens.
How to use it
- Press Load next page. The phone gets 10 more posts.
- Press A new post arrives at the top. Then press Load next page again.
- Switch from page numbers to the cursor. Try the same steps.
- Allow double taps. Then press Tap Load next page twice, fast.
- Press A post is deleted on the server. Then press Load next page with page numbers, and look for a missed post.
The tool
What this shows
On the server
On the phone
- 51repeat A post that shows twice (stripes)
- 50missed A post the phone never got (dots)
- 61new A new post, not loaded yet
- 56deleted Deleted on the server, still on the phone
Repeated posts
Missed posts
Page requests sent
Posts on the phone
How the model works
- The server has 60 posts, newest first. Post 60 is the newest. A new post gets the next number, 61, and goes at the top.
- The phone loads 10 posts for each request.
- With page numbers (offset), page 2 means rows 11 to 20 of the server list at that moment. The phone counts rows.
- With a cursor, the server gives the phone a saved place after each page. The phone sends it back without reading it. The server sends the 10 posts after that place.
- With one request at a time, a second tap is ignored while a request is running. The library does the same: it allows one running load for each direction.
- Refresh drops the list on the phone and loads the first page again.
- A repeated post shows more than once on the phone. A missed post is on the server, between the newest and the oldest post on the phone, but not on the phone. A new post above the newest post on the phone is not missed. It waits for a refresh.
- There are no random numbers. The same steps always give the same result.
Without JavaScript
The tool needs JavaScript. This table writes out the four examples, step by step. Each example starts with the same lists: the server has posts 60 to 1, and the phone shows posts 60 to 51.
| Example | What happens | After | What it shows |
|---|---|---|---|
| Page numbers with a new post arriving Page numbers (offset), one request at a time | Post 61 arrives at the top of the server. The phone loads page 2. | Server: posts 61 to 1. Phone: posts 60 to 51, then 51 to 42. Repeated: 1 (post 51). Missed: 0. Post 61 is new and waits for a refresh. | A page number counts rows. The new post moved every row down by one, so post 51 came twice. |
| Cursor with a new post arriving Cursor, one request at a time | Post 61 arrives at the top of the server. The phone loads the next page with its cursor. | Server: posts 61 to 1. Phone: posts 60 to 41. Repeated: 0. Missed: 0. Post 61 is new and waits for a refresh. | The cursor is a saved place, not a row number. The new post at the top does not move it. |
| Double tap without a guard Cursor, double taps allowed | The reader taps Load next page twice, fast. The phone sends two requests with the same cursor. | Server: posts 60 to 1. Phone: posts 60 to 41, then 50 to 41. Repeated: 10 (posts 50 to 41). Missed: 0. Page requests sent: 3, not 2. | A cursor does not stop a double request. Sending one request at a time does. |
| Delete during paging Page numbers (offset), one request at a time | Post 56 is deleted on the server. The phone loads page 2. | Server: posts 60 to 1 without post 56. Phone: posts 60 to 51, then 49 to 40. Repeated: 0. Missed: 1 (post 50). Post 56 is deleted but still on the phone. | A page number counts rows. The delete moved every row up by one, so post 50 moved into rows the phone already had. |
What this model leaves out
- A cursor does not stop every problem. If the server changes the ranking between two pages, a post can still repeat. The app removes repeats by post ID.
- The model does not use a cursor that has expired, or a lost network. In the case study, an expired cursor gives a typed error, and then the app refreshes.
- The model has no prefetch (loading before the reader asks). You press a button instead, so you can see each step. A fast scroll can send many requests for the same place, as the double tap does here.
Read more
- Design a pagination library, the case study behind this tool
- The pagination library build guide
- Design a news feed, where cursor paging is used for the feed
- Glossary: cursor, paging, prefetch