All specs
uxhigh complexity

Activity Feed

Used in 3 specs

Show users a chronological or ranked stream of relevant events — follows, posts, mentions, workspace activity — with real scaling considerations.

Options

Fan-out Architecture*

Store events once; when a user requests their feed, query and merge sources on demand.
When an event is produced, write a copy into each follower's feed.
Push events to follower feeds up to a follower-count threshold; pull inline for celebrity accounts.

Ordering & Ranking*

Newest first, no ranking model.
Items scored by predicted relevance (affinity, recency, engagement signals).
Split the feed into curated sections (e.g. "Mentions", "Replies", "All activity").

Feed Capabilities

Show 'N new items' while the feed is open; insert on click.
"Alice, Bob, and 12 others liked your post" instead of 14 rows.
Edits and deletions to source content update the feed copies (push model).

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

CostFan-out on write

Read speed gains paid for by write amplification — cost scales with follower counts

ComplexityEngagement ranking

Model training, feedback collection, and trust-and-safety review all expand

ComplexityReal-time updates enabled

Requires a pub/sub layer (overlaps with notifications infra)

Dependencies

user-system

Implementation Examples

Stream

Feeds-as-a-service with fan-out, ranking, and aggregation primitives.

Instagram Engineering — Fanout

Public writeups on scaling fan-out and ranking for very large consumer feeds.

Activitypub

Reference for a federated feed protocol — useful vocabulary for feed entity modeling.

Used by specs

Social / Community AppNote-taking / Knowledge BaseProject Management Tool