Twitter/X Timeline: Trade-offs & Decisions
The core architectural decisions in a social timeline system — alternatives considered, reasons for each choice, and where different approaches make sense.
Fanout-on-Write vs Fanout-on-Read
The central trade-off in timeline design: where does the computation happen?
Fanout-on-write (push)
Timeline read cost is bounded and does not depend on how many accounts the user follows — just read the pre-built inbox. Write cost is O(followers). Best when: follower counts are bounded and predictable. Worst when: a user has millions of followers — one post can overwhelm the entire write pipeline.
Fanout-on-read (pull)
Write cost is constant per post. Read cost grows with the number of accounts followed. Best when: you can't predict follower counts (or they're unbounded). Worst when: users follow many accounts — each timeline load triggers many queries.
Strong vs Eventual Consistency
Should a follower see a new post immediately, or is a few seconds of delay acceptable?
Strong consistency
A follower opens their timeline and immediately sees the post. Requires synchronous fanout — the post creator waits for all inbox writes to complete before their post is considered "created." For 50M followers: not feasible. For 500 followers: feasible but unnecessarily slow.
Eventual consistency
Fanout is asynchronous. The post is created instantly from the creator's perspective. Followers see it after fanout workers process the job — typically seconds to tens of seconds under normal load (illustrative; longer while a fanout backlog drains, as the Instagram trade-offs page describes as "seconds to minutes" for the same mechanism). For a social feed, this delay is imperceptible and completely acceptable.
Chronological vs Ranked Feed
Should timelines show posts in reverse chronological order, or ranked by relevance?
Chronological
Simple. Predictable. Transparent to users — they know exactly why each post appears. Easy to implement. Easy to debug. Trade-off: a post from someone the user cares about deeply might be buried by dozens of less interesting posts.
Ranked
Surfaces content the user is most likely to engage with. Better for user retention and engagement. Requires a machine learning model, training data, feature pipelines, and ongoing iteration. Can feel opaque or arbitrary to users.
Cache TTL and Freshness
How fresh must the cached timeline be? A shorter TTL means fresher content but more recomputation.
Short TTL (a few seconds)
Near real-time timelines. High recomputation cost — most reads trigger a full composition pass. Better user experience for active users who expect immediate feed updates.
Long TTL (minutes)
Lower recomputation cost. Users may miss a post for several minutes. Acceptable for a social feed where eventual consistency is already the expectation. Dramatically higher cache hit rate.
Fixed Threshold vs Adaptive Fanout Policy
How should the system decide which authors get push (fanout-on-write) vs pull (fanout-on-read) distribution?
Fixed follower-count threshold
Simple, predictable, and easy to operate. Follower count is a reasonable proxy for fanout cost. But it ignores posting frequency and how many of those followers are actually active — two authors with the same follower count can have very different real fanout cost.
Adaptive classification
Considers follower count alongside posting frequency, active-follower ratio, current queue pressure, and observed fanout cost for that account. Better fits real workload variation, but adds operational complexity, and a classification boundary that can oscillate is harder to reason about than a single static number.
Store Post IDs vs Full Post Objects in Timeline Inboxes
Should a follower's precomputed timeline inbox store full copies of each post, or just references to them?
Full post copies
Fewer hydration lookups at read time — the data is already sitting in the inbox. But this means enormous duplication across millions of inboxes, makes content edits or deletion much harder to propagate, leaves engagement counts as stale copies that drift from the real value, and inflates per-user inbox memory.
IDs / references only
Compact, and lifecycle handling stays simple because post content remains centralized in one place. A shared object cache can hydrate IDs efficiently across many inboxes at once. The cost is one additional hydration step at read time.
Offset vs Cursor Pagination for Timeline
How should a client page through an infinite, continuously changing feed?
Offset pagination
Simple API semantics ("give me results 20-40"), but unstable and inefficient against a feed that keeps changing underneath it — new posts and shifting ranked scores can cause duplicate or skipped results between page requests.
Cursor / continuation token
Better suited to a continuously changing, ordered result — each page carries enough state to continue exactly where the previous one left off. The cost is more server-side state and implementation complexity than a plain offset.