The feed list takes about 320ms to load: six queries per feed #94

Closed
opened 2026-09-29 09:39:39 -07:00 by rays · 1 comment
Owner

GET /api/feeds is the slowest route by far: 95th percentile about 310ms over the last hour, every trace 300-660ms, against 63ms for the next slowest (/api/entries). It is asked for on every page load and after every refresh.

The handler (web.rs, feeds) loops over the subscriptions and, for each feed, calls feed_summary (the feed row, a count of its entries, a count of its downloads), http_state (the feed row again), blocklist and unread_count: six round trips to Postgres per feed, about 950 for 160 feeds. The trace shows no child spans, only the handler's 320ms.

Fix: one query each for the feed rows, entry counts by feed, download counts by feed, unread counts by feed for the user, and the user's blocklists, then assemble in memory. Five queries whatever the feed count.

TraceQL: {resource.deployment.environment.name="production" && name = "GET /api/feeds"}; e.g. trace 35c75eca252e5effb54e373555211ad3 (319ms).

GET /api/feeds is the slowest route by far: 95th percentile about 310ms over the last hour, every trace 300-660ms, against 63ms for the next slowest (/api/entries). It is asked for on every page load and after every refresh. The handler (web.rs, `feeds`) loops over the subscriptions and, for each feed, calls feed_summary (the feed row, a count of its entries, a count of its downloads), http_state (the feed row again), blocklist and unread_count: six round trips to Postgres per feed, about 950 for 160 feeds. The trace shows no child spans, only the handler's 320ms. Fix: one query each for the feed rows, entry counts by feed, download counts by feed, unread counts by feed for the user, and the user's blocklists, then assemble in memory. Five queries whatever the feed count. TraceQL: {resource.deployment.environment.name="production" && name = "GET /api/feeds"}; e.g. trace 35c75eca252e5effb54e373555211ad3 (319ms).
rays added the bug label 2026-09-29 09:39:39 -07:00
Author
Owner

Fixed in e8fd3fe: Db::feed_list answers the feed list in five queries whatever the feed count. In production after the deploy (2026-09-29 17:28 UTC), GET /api/feeds takes 48-71ms, down from about 320ms.

Fixed in e8fd3fe: Db::feed_list answers the feed list in five queries whatever the feed count. In production after the deploy (2026-09-29 17:28 UTC), GET /api/feeds takes 48-71ms, down from about 320ms.
rays closed this issue 2026-09-29 10:32:33 -07:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rays/ipx#94