|3.27Mins Read

Stable Shuffled Pagination with Time-Based Seeds: Avoiding Repetition Across Pages

Authors
Stable Shuffled Pagination with Time-Based Seeds: Avoiding Repetition Across Pages

In user-facing feeds like nature content, product listings, or discovery platforms, it's often desirable to present items in a shuffled (random) order while still supporting pagination. However, combining randomness, pagination, and consistency is tricky, especially when the shuffle changes over time (e.g., daily). This article introduces the concept of Stable Shuffled Pagination, highlights a key edge case, and outlines how to avoid it.


What Is Stable Shuffled Pagination?

Stable Shuffled Pagination is a technique where a list of items is presented in a randomized order that supports:

  • Pagination: Users can load page 1, 2, 3... etc.
  • Stable Order: The random shuffle stays the same across multiple page requests.
  • Non-repetition: Items seen on one page do not appear again on the next.
  • Periodic Change (Optional): The order changes daily, weekly, or based on a seed.

This is often implemented using a deterministic random shuffle, seeded by a value like the current date (e.g., 2025-06-19).


The Edge Case: Seed Flip During Pagination

Scenario:

  1. A user opens your app on June 19 and begins browsing nature content.

  2. They navigate to Page 4 β€” the feed is seeded by 2025-06-19, showing a consistent, randomized order.

  3. Midnight hits; the seed changes to 2025-06-20.

  4. The user now loads Page 5 β€” it uses a new shuffle order.

  5. As a result:

    • Items from Page 1–4 may reappear.
    • The content flow feels broken or confusing.

This problem arises because the seed used to shuffle changed mid-session.


Solutions to Ensure Stable Experience

1. Include the Seed in Every Request

Lock the seed at the start of the session and pass it with every paginated request:

GET /feed?page=5&seed=2025-06-19

This ensures the same shuffle is used for all pages during the user's session.

2. Use Token-Based Pagination

Encode both the seed and the offset into a single token:

GET /feed?token=eyJzZWVkIjoiMjAyNS0wNi0xOSIsIm9mZnNldCI6MzB9

This token is stateless, yet deterministic β€” it locks in the session's random order.

3. Store Shuffle Session Server-side

Maintain the shuffled order or seed per session on the server. While this works, it requires session management and cleanup, making it less scalable.

4. Use Long-Lived Seeds

Instead of switching shuffle order daily, switch weekly or on-demand (e.g., pull to refresh). This avoids mid-session flips at midnight.

5. Generate and Persist Seed on Client Side (e.g., Flutter BLoC)

For frontend-controlled sessions, generate a random seed on page load or refresh and store it in memory (like in a BLoC class). Use this seed for all paginated requests:

class FeedBloc extends Cubit<FeedState> {
  final String seed = Uuid().v4();

  void fetchPage(int page) {
    api.fetchFeed(seed: seed, page: page);
  }

  void resetFeed() {
    final newSeed = Uuid().v4();
    // update state and reload page 1 with new seed
  }
}

This approach guarantees:

  • A different shuffle for each refresh.
  • No repeats across pages.
  • Stateless backend requests with deterministic behavior.

Best Practices Summary

StepWhat to Do
πŸ”’ Seed ShuffleUse deterministic seed (e.g., date or UUID)
β›“ Lock the SessionInclude seed in all paginated requests
πŸ” Protect From DriftDon't auto-change seed mid-session
πŸ’Ύ Optional: CacheStore shuffled result or use consistent PRNG
✨ Frontend ControlGenerate & manage seed at client level if needed

Final Thoughts

Stable Shuffled Pagination enables dynamic and engaging content presentation without compromising on UX or data consistency. But to avoid repetition and confusion, especially during time-based seed changes, it’s crucial to pass the seed consistently across pagination requests.

By adopting one of the recommended strategies above β€” including client-side seed control β€” you can deliver a feed that feels fresh, stable, and user-friendly.