Activity Feed
Show users a chronological or ranked stream of relevant events — follows, posts, mentions, workspace activity — with real scaling considerations.
Options
Fan-out Architecture*
Ordering & Ranking*
Feed Capabilities
Decision Points
Do you expect users to follow accounts with very large follower counts?
If yes
Pull-on-read or hybrid; pure fan-out-on-write will bury you in writes.
If no
Fan-out on write gives you the fastest reads for typical workloads.
Is the feed for a consumer social app or a workspace productivity tool?
If yes
Consumer: plan for ranking and grouping. Productivity: start chronological and sectioned.
If no
Defaults above still apply by category.
Is the feed personalized/ranked or strictly chronological?
If yes
Go with engagement-ranked — budget for model training, signal collection, and a feedback loop.
If no
Reverse-chronological is predictable and debuggable; sectioned adds structure without ML.
Do you need cross-entity aggregation ("Alice did X, Y, Z") or flat events?
If yes
Enable grouping/collapsed actions. Group by (actor, action, target, time window) and re-collapse on new matching events.
If no
Flat event rows are simpler — skip grouping until the feed visibly floods.
Will inactive users get the feed as an email digest?
If yes
Layer a digest job on top — roll up the last N events per user and send via your transactional email provider on a cadence.
If no
Keep the feed in-app only; rely on notifications for re-engagement.
Do users follow other users, or is the feed account-scoped?
If yes
You need a follow graph and fan-out strategy — pull-on-read to start, hybrid once celebrity accounts emerge.
If no
Scope the feed to a single account/workspace — no follow graph, just filter by tenant.
Must the feed backfill historical events at signup?
If yes
Run a backfill job on signup that populates the user feed from the event log — pull-on-read makes this trivial; push requires explicit backfill.
If no
Start the feed from signup time onward; simpler and avoids reading cold history.
Is read volume high enough to justify precomputed timelines (fan-out on write)?
If yes
Use push-on-write or hybrid — precomputed per-user feeds turn reads into a single indexed query.
If no
Pull-on-read is cheaper and simpler until reads dominate your workload.
Do you need private/scoped feeds (team, project, channel)?
If yes
Model feed scope as a first-class field on each entry and enforce ACL at query time — Linear/GitHub style.
If no
A single global per-user feed is simpler to model and query.
Should the feed include system-generated events (badges, milestones)?
If yes
Add a "system" actor type and treat these as first-class events — same schema, different source.
If no
Keep the feed user-driven; surface system events elsewhere (notifications, profile).
Is infinite scroll required, or is pagination acceptable?
If yes
Use cursor-based pagination with an intersection observer — offset pagination breaks when items shift.
If no
Classic page-based pagination is fine for lower-engagement feeds.
Do you need real-time insertion of new items at the top?
If yes
Enable real-time updates — SSE or WebSocket with an "N new items" indicator; insert on user click to avoid layout jumps.
If no
A pull-to-refresh or periodic re-fetch is enough.
Will users filter the feed by activity type?
If yes
Use a sectioned layout (Mentions / Replies / All) or add filter chips backed by an indexed action-type column.
If no
A single stream is simpler and avoids empty-state UX for rare filters.
Must low-value events ("X viewed Y") be suppressed?
If yes
Add a signal-score threshold at write-time or a "collapse low-signal" toggle in the feed renderer.
If no
Log everything and let users filter — but expect noise complaints.
When a source object is deleted, should its feed entries disappear?
If yes
Propagate deletes with edit/delete-sync — store entry version IDs and tombstone on source deletion.
If no
Accept eventual-consistency staleness and surface "content unavailable" at render time.
Is ranking ML/collaborative filtering or rule-based scoring?
If yes
Start rule-based (recency + engagement + affinity weights) — a linear scorer beats ML until you have signal volume.
If no
Stay chronological until ranking is measurably worth the investment.
Does each feed item need a stable permalink?
If yes
Mint stable IDs on write and expose a `/feed/:id` route — required for notifications that deep-link into the feed.
If no
Treat the feed as ephemeral — simpler, but no deep-linking from emails or notifications.
Tradeoffs
Read speed gains paid for by write amplification — cost scales with follower counts
Model training, feedback collection, and trust-and-safety review all expand
Requires a pub/sub layer (overlaps with notifications infra)