Skip to content

SCIX-897 feat: reconcile rate limiting and 429 error handling#901

Draft
thostetler wants to merge 2 commits into
adsabs:masterfrom
thostetler:feature/scix-897-429-rate-limit-handling
Draft

SCIX-897 feat: reconcile rate limiting and 429 error handling#901
thostetler wants to merge 2 commits into
adsabs:masterfrom
thostetler:feature/scix-897-429-rate-limit-handling

Conversation

@thostetler

@thostetler thostetler commented Jul 14, 2026

Copy link
Copy Markdown
Member

The node edge middleware's IP rate limiter redirected rate-limited users to the
home page with a generic toast, so its 429s and the upstream API gateway's 429s
took different code paths and no caller ever saw a real HTTP 429. Users got
inconsistent feedback and no path to a higher limit.

  • Middleware returns a real HTTP 429 with Retry-After instead of redirecting: a
    minimal HTML page for document navigations, JSON for XHRs
  • Node and upstream 429s flow through one client path: a toast for background
    requests and an inline SearchErrorAlert for foreground queries
  • 429 copy encourages account creation, but only for anonymous users;
    authenticated users and the auth-unaware parseAPIError get a plain message
  • Exempted the auth routes and /api/user from the node limiter so the
    account-creation link stays reachable when rate limited
  • Stopped retrying 429 search requests; React Query stays retry:false
  • Unified the 429 wording across the toast, inline alert, and full-page

Authenticated:
image5
image4
image2

Anonymous:
image3
image1
image6

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.68182% with 34 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.0%. Comparing base (2be2c28) to head (a4d0453).

Files with missing lines Patch % Lines
src/components/SolrErrorAlert/SolrErrorAlert.tsx 46.9% 17 Missing ⚠️
src/api/api.ts 55.6% 8 Missing ⚠️
src/store/store.ts 64.3% 5 Missing ⚠️
src/api/search/search.ts 50.0% 4 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master    #901     +/-   ##
========================================
+ Coverage    67.0%   67.0%   +0.1%     
========================================
  Files         346     347      +1     
  Lines       41042   41410    +368     
  Branches     2084    2132     +48     
========================================
+ Hits        27489   27744    +255     
- Misses      13508   13621    +113     
  Partials       45      45             
Files with missing lines Coverage Δ
src/lib/useSolrError.ts 75.8% <100.0%> (ø)
src/middleware.ts 92.4% <100.0%> (+0.9%) ⬆️
src/rateLimit.ts 47.0% <100.0%> (+3.5%) ⬆️
src/store/slices/notification.ts 90.3% <100.0%> (+0.5%) ⬆️
src/utils/common/parseAPIError.ts 100.0% <100.0%> (ø)
src/api/search/search.ts 56.1% <50.0%> (-0.1%) ⬇️
src/store/store.ts 46.7% <64.3%> (+2.1%) ⬆️
src/api/api.ts 82.9% <55.6%> (-1.3%) ⬇️
src/components/SolrErrorAlert/SolrErrorAlert.tsx 37.0% <46.9%> (ø)

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The node IP limiter redirected rate-limited users to / with a generic
toast, so its 429s and upstream API 429s took different paths and no
caller saw a real status. Reconcile them, with dedicated auth-aware copy.

1. Middleware returns a real 429 (+ Retry-After) instead of redirecting —
   an HTML page for document navigations, JSON for XHRs
2. Node and upstream 429s share one client path: a toast for background
   requests, an inline SearchErrorAlert for foreground queries
3. Only anonymous users get the account-creation CTA; authenticated users
   (and the auth-unaware parseAPIError) get a plain message
4. Exempt the whole /user/account/ auth surface and /api/user from the node
   limiter so the CTA and emailed verify/reset links stay reachable
5. Stop retrying 429 search requests; React Query stays retry:false
parseAPIError 429 detection + plain copy, and useSolrError 429 mapping
with auth-conditional inline copy.
@thostetler thostetler force-pushed the feature/scix-897-429-rate-limit-handling branch from 9d7ea36 to a4d0453 Compare July 14, 2026 19:43
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.

1 participant