What Is a Watchlist Service?
A watchlist service lets users curate personal lists of content items they intend to watch, reorder those lists by custom priority, synchronize the list state across all their devices, and optionally surface watchlist items in personalized recommendations. It is a staple feature of streaming and VOD platforms where content libraries are large and users need a persistent personal queue.
Requirements
Functional Requirements
- Add, remove, and reorder items in a user watchlist.
- Support multiple named lists per user (e.g., Watch Later, Favorites, Shared with Partner).
- Persist custom priority ordering set by the user via drag-and-drop.
- Sync list state across devices: a change on mobile is reflected on TV within a few seconds.
- Expose a hook for the recommendation engine to query a user watchlist as a signal.
- Support bulk operations: add or remove up to 50 items in a single request.
Non-Functional Requirements
- Read latency under 30 ms P99 for list fetch.
- Cross-device sync propagation under 5 seconds P95.
- Support up to 10,000 items per list without degraded query performance.
Data Model
WatchList
list_idUUID — primary key.user_id,name,is_defaultboolean.created_at,updated_attimestamps.
WatchListItem
item_idUUID — primary key.list_idFK,content_id.positionFLOAT — fractional indexing value for O(1) reordering.added_attimestamp.- Unique constraint on
(list_id, content_id)to prevent duplicates.
SyncCheckpoint
user_id,device_id— composite primary key.last_seqBIGINT — highest change sequence number the device has acknowledged.synced_attimestamp.
Core Algorithms
Fractional Indexing for Priority Ordering
Rather than storing integer positions and renumbering all items on every reorder, positions are stored as floats. Moving an item between positions A and B assigns it the value (A + B) / 2. This allows single-row updates for any reorder operation. When the gap between adjacent positions falls below a minimum epsilon (indicating precision exhaustion after many reorders), a background job renormalizes the positions for the affected list by assigning evenly spaced floats, preventing precision loss over time.
Cross-Device Sync via Change Log
Every mutation (add, remove, reorder) appends a record to a WatchListChange log table with an auto-incrementing sequence number scoped to the user. Each device tracks its last_seq in the SyncCheckpoint table. On reconnect or foreground resume, the client calls GET /v1/sync?since={last_seq} and receives all changes since its last checkpoint as a delta. The client applies the delta to its local state and updates last_seq. This pull-based model keeps logic simple and avoids stateful push connections for background sync, while a WebSocket push channel is used for real-time sync when the app is in the foreground.
Conflict Resolution
If two devices modify the same item concurrently (e.g., both reorder it offline), the conflict is resolved by last-write-wins based on the server-assigned sequence number. Since watchlist operations are low-stakes (no financial consequence), this strategy is acceptable. Each change record includes the device_id that originated it so clients can identify their own pending changes and apply optimistic UI updates before the server confirms.
API Design
GET /v1/lists— returns all lists for the authenticated user.GET /v1/lists/{list_id}/items?page=&size=— paginated items ordered by position.POST /v1/lists/{list_id}/items— add one or more items; body: array ofcontent_id.DELETE /v1/lists/{list_id}/items/{content_id}— remove an item.PATCH /v1/lists/{list_id}/items/{content_id}— update position (reorder).GET /v1/sync?since={seq}— delta sync endpoint; returns changes since the given sequence.
Scalability and Recommendation Integration
Read Path
List items are cached in Redis sorted sets keyed by list_id, with the fractional position as the sorted set score. List reads are served from Redis with a 30-second TTL. On cache miss, items are loaded from PostgreSQL and repopulated. Writes invalidate the Redis key immediately and write through to PostgreSQL synchronously to ensure consistency.
Recommendation Hook
The recommendation engine queries watchlist items for a user via an internal gRPC call: GetWatchlistItems(user_id, list_id). The response is used as a negative signal (do not re-recommend already-listed items) and a positive signal (recommend items similar to those on the list). This integration is read-only and served from the Redis cache, so it adds no write-path coupling.
{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “How are CRUD operations managed for a watchlist service?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Each user has one or more named lists stored as ordered sets in the database. Add and remove operations are idempotent (upsert/delete by item ID). List reads return items in the stored order with metadata (title, poster, added_at). Soft deletes are preferred so items can be restored, with a background job purging old deleted entries after a retention window.”
}
},
{
“@type”: “Question”,
“name”: “How is custom priority ordering implemented in a watchlist?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Items are stored with a floating-point rank field. Reordering uses the fractional indexing pattern: the new rank is set to the midpoint between the ranks of the surrounding items. When rank precision is exhausted (values converge), a background normalization job reassigns evenly spaced integer ranks. This avoids full-list rewrites on every drag-and-drop operation.”
}
},
{
“@type”: “Question”,
“name”: “How does cross-device sync work for a watchlist?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “The server is the source of truth. Clients pull the current list on session start with an ETag/version token. Mutations are sent to the server immediately and also queued locally for offline support. On reconnect, the client replays queued operations against the server version, with last-write-wins or CRDT merge semantics resolving conflicts. Push notifications (WebSocket or SSE) propagate changes to other active devices in real time.”
}
},
{
“@type”: “Question”,
“name”: “How are watchlist signals used for recommendation integration?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Add-to-watchlist events are strong positive intent signals (stronger than a click, weaker than a completion). The recommendation system subscribes to these events via a message bus and updates the user's long-term interest vector in the feature store. Items on the watchlist are suppressed from “recommended for you” feeds to avoid redundant promotion, and their genre/tag attributes reinforce affinity weights for cold-start and collaborative filtering models.”
}
}
]
}
See also: Anthropic Interview Guide 2026: Process, Questions, and AI Safety
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering