stakwork / stakwork/hive

[Critical] Add pagination to feature endpoints to prevent performance issues

Open
#1,908 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
5
Forks
17
Avg merge
3h 45m
Merged PRs (30d)
220

Description

Problem

Currently, GET /api/features/[featureId] returns the entire feature with ALL phases and ALL tasks in a single response. This creates several issues:

  • Unbounded response size: A feature with 200 tasks results in a multi-MB JSON response
  • Browser performance: React rendering hundreds of task rows can freeze the UI
  • Network timeouts: Large responses timeout on slow connections
  • Scale ceiling: System will break at ~200 tasks per feature
Current Implementation

API Route: /src/app/api/features/[featureId]/route.ts

// Returns everything at once
const feature = await getFeature(featureId, userId);
// Includes: feature.phases[].tasks[] - unbounded arrays

Type Definition: /src/types/roadmap.tsx

export interface FeatureDetail {
  phases: PhaseWithTasks[];  // Each phase has tasks: TicketListItem[]
  // No pagination metadata
}

Frontend: /src/app/w/[slug]/roadmap/[featureId]/page.tsx

  • Fetches entire feature on mount
  • Passes all tasks to TicketsList component
  • No virtualization or windowing

Proposed Solution

Lazy-load tasks when user navigates to Tasks tab

Phase 1: Separate endpoints

GET /api/features/[featureId]  // Feature + phases metadata only (no tasks)
GET /api/features/[featureId]/tasks?page=1&limit=50  // Paginated tasks

Phase 2: Frontend changes

  • Feature detail page fetches feature without tasks
  • Tasks tab triggers separate fetch when user clicks "Tasks"
  • Add virtual scrolling with react-window for task list rendering

Phase 3: Backend optimization

  • Add cursor-based pagination for efficient queries
  • Return pagination metadata: { data: [], pagination: { total, page, limit, hasMore } }
Alternative: Query parameter approach
GET /api/features/[featureId]?includeTasks=false  // Default: exclude tasks
GET /api/features/[featureId]?includeTasks=true&tasksPage=1&tasksLimit=50

Success Criteria

  • Feature with 500 tasks loads in <2 seconds
  • Browser doesn't freeze when rendering task list
  • API response size stays under 1MB regardless of task count
  • Tasks are fetched only when user navigates to Tasks tab

Code References

  • /src/app/api/features/[featureId]/route.ts - API route handler
  • /src/services/roadmap/features.ts - getFeature service function
  • /src/types/roadmap.tsx - FeatureDetail type (lines 620-640)
  • /src/components/features/TicketsList/index.tsx - Frontend component that renders tasks

Effort Estimate

2-3 weeks

  • Backend API changes: 3-4 days
  • Frontend refactoring: 4-5 days
  • Virtual scrolling implementation: 2-3 days
  • Testing and optimization: 3-4 days

Priority

Critical - This will become a blocker as features grow beyond 50-100 tasks.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/app/api/features/[featureId]/route.ts and src/services/roadmap/features.ts to trace how phases and tasks are loaded, then review FeatureDetail in src/types/roadmap.tsx and TicketsList in src/components/features/TicketsList/index.tsx. Define the endpoint and loading changes needed for lazy, paginated tasks and verify the success criteria: bounded responses, no UI freeze, and tasks fetched only on the Tasks tab.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
api, frontend, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.