Skip to main content
← Back to list
01Issue
BugOpenSwamp CLIPublic
AssigneesNone

Relationships

≡ duplicate of #3407

#3444 Dashboard: a live run page polls a full workflow.run.search every 2.5 s, and time-range presets refetch the run summary every minute

Opened by hammz · 10/14/2026

Description

Two dashboard request patterns keep resending the expensive run queries from #3443. Every one of those requests reads the run index of every workflow, for all time. These patterns turn that per-request cost into constant load on serve.

1. A live run page polls a full run search every 2.5 s

RunDetail.tsx polls refetchRun every LIVE_POLL_MS = 2500 while the run is live (usePolling(refetchRun, live ? LIVE_POLL_MS : null)). refetchRun refetches three requests:

  • workflow.history.get: cheap for a full run id (findGlobalById).
  • workflow.history.logs, tail 200.
  • workflow.run.search { workflow, query: runId, limit: 1 }. This reads the run index of every workflow and builds a search item for every run ever kept, only to return one row. query is a substring post-filter, so the run id does not narrow the read.

So each open tab on a running run triggers a scan of all history every 2.5 s. On a repo with about 100k runs that is about 400 ms of serve's only thread every 2.5 s, per tab (see #3443 for the numbers). Long runs, or several people watching a deploy, add up. useActiveRunsRefetch also calls the same refetchRun when the health snapshot's active runs change.

2. Time-range presets re-key the run summary every minute

useTimeBounds() (client/time_range.ts) rounds Date.now() to the minute during render. The health stream re-renders the app every 5 s, so on the first render after a minute rolls over, the preset's since/until change. The useRequest key changes with them, which sends the request again. Every page using useRunSummary with the dashboard range therefore refetches once a minute while open:

  • Workflows: workflow.run.summary { recentLimit: 20 }
  • Overview: { timeline: true, recentLimit: 0 }
  • Executions: two summaries
  • Approvals, and trigger_runs.ts (schedules and webhooks)

Each refetch is a full scan. The Workflows page already keeps the previous summary on screen to hide the flash (held in Workflows.tsx), but the server work still happens every time. For a "last 7 days" range, moving the window by one minute almost never changes the result.

Steps to reproduce

  1. Use a repo with a large run history, about 100k runs.
  2. Open a run while it is running. Watch serve's swamp.workflow.run_search spans: one every 2.5 s per tab.
  3. Leave the Workflows or Overview page open on a preset range: one swamp.workflow.run_summary per minute per tab.

Expected

  • Live run page: poll only what changes for a live run, workflow.history.get and .logs. Read the run-search row (trigger, awaiting-resume) once, and again only when the status changes or the health snapshot's active runs change. Or, once #3443 lands, use a by-id lookup that doesn't scan.
  • Preset ranges: don't re-key a run summary only because the clock moved. Options:
    • Send the preset as a relative bound (since: "7d"; the server already accepts durations) so the key stays stable.
    • Coarsen the rounding to the range's size, for example an hour for ranges of a day or more.
    • Refetch on a deliberate interval, or when the health snapshot shows runs started or finished, rather than on each minute's rollover.
  • Request volume from an open dashboard tab should not depend on how long the tab stays open.

Related: #3443 (the server-side cost of each of these requests), #3335 (dashboard overhaul).

02Bog Flow
◉OPEN○TRIAGED○IN PROGRESS○SHIPPED

Open

10/14/2026, 2:00:27 PM

No activity in this phase yet.

03Sludge Pulse
stack72 linked duplicate of #340710/14/2026, 2:03:32 PM

Sign in to post a ripple.