Skip to content

Fix slow page loads: parallelize homepage fetches, restore caching, fix senators N+1 - #209

Merged
calebyhan merged 1 commit into
mainfrom
205/fix-slow-page-loads
Aug 22, 2026
Merged

Fix slow page loads: parallelize homepage fetches, restore caching, fix senators N+1#209
calebyhan merged 1 commit into
mainfrom
205/fix-slow-page-loads

Conversation

@calebyhan

Copy link
Copy Markdown
Contributor

Users reported the site sometimes takes a while to load. Investigation (issue #205) found three separate, compounding causes — a sequential fetch waterfall on the homepage, caching disabled on several admin-editable pages, and an N+1 query pattern on the senators API.

Changes:

  • frontend/src/app/page.tsx, RecentNews.tsx — the homepage awaited getCarousel(), getEvents(), getFinanceHearings(), and (via the nested RecentNews server component) getNews() sequentially, meaning every visit stacked 4 backend round trips in series. Switched to Promise.allSettled so they run concurrently, and turned RecentNews into a plain presentational component that receives its data as a prop instead of fetching on its own.
  • frontend/src/lib/api.tsfetchAPI hardcoded cache: "no-store", so admin-editable pages (staff, leadership, committees, finance hearings) re-fetched from the backend on every single request with zero caching. Added an optional revalidateSeconds param and switched getStaff, getLeadership, getCommittees, getCommitteeById, and getFinanceHearings to a 60s revalidate window — admin edits still show up within a minute, but requests in between are served from cache instead of hitting the backend live.
  • backend/app/routers/senators.py, models/Senator.pylist_senators issued 2 extra DB queries per senator (2N + 1 total) instead of eager-loading committee memberships, unlike committees.py's equivalent endpoint which already uses selectinload correctly. Fixed by eager-loading via selectinload in _base_query. This also surfaced a real bug in the model: Senator.committee_memberships was typed as bare Mapped[list] (no type param), which made SQLAlchemy infer uselist=False and silently return a single row or None instead of a list — exactly the landmine the old code's docstring said it was working around by hand-querying instead of using the relationship. Fixed the annotation to Mapped[list["CommitteeMembership"]].

Verified: all 588 backend tests pass, tsc --noEmit is clean, and next build confirms /about/staff, /committees, /funding/apply, /senators/leadership flipped from fully dynamic (ƒ) to ISR (, 1m revalidate).

Closes #205

…ix senators N+1

The homepage awaited getCarousel/getEvents/getFinanceHearings/getNews
sequentially instead of concurrently. Several admin-editable pages had
caching fully disabled (cache: "no-store" in fetchAPI, no revalidate
window) so every visit re-fetched from the backend live. And the
senators list endpoint issued 2 extra DB queries per senator instead
of eager-loading committee memberships.

- frontend/src/app/page.tsx, RecentNews.tsx: fetch homepage data via
  Promise.allSettled instead of sequential awaits; RecentNews is now a
  presentational component fed data as a prop.
- frontend/src/lib/api.ts: fetchAPI takes an optional revalidateSeconds
  param; getStaff/getLeadership/getCommittees/getCommitteeById/
  getFinanceHearings now use a 60s revalidate window instead of
  no-store, restoring ISR caching between admin edits.
- backend/app/routers/senators.py, models/Senator.py: eager-load
  committee memberships via selectinload instead of querying per
  senator. Also fixes Senator.committee_memberships being typed as
  bare Mapped[list] (no type param), which made SQLAlchemy infer
  uselist=False and silently return a single row/None instead of a
  list.

Closes #205
@github-actions

Copy link
Copy Markdown

Test Results

588 tests  ±0   588 ✅ ±0   52s ⏱️ +18s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 5158d81. ± Comparison against base commit b5ceec3.

@MasonMines2006 MasonMines2006 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@calebyhan
calebyhan merged commit 75c81ab into main Aug 22, 2026
3 checks passed
@calebyhan
calebyhan deleted the 205/fix-slow-page-loads branch August 22, 2026 02:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Site is slow to load — sequential fetch waterfall, blanket cache opt-out, and N+1 senators query

2 participants