Skip to content

perf(approvals): server-side pagination + pushdown filtering for listRequests #1745

Description

@os-zhuang

Context

ApprovalService.listRequests hard-caps at limit: 500 and returns everything in one shot; the Console inbox (objectstack-ai/objectui, ApprovalsInboxPage) sorts/filters/searches client-side. The request table is append-only (every flow trigger adds a row), so a real tenant crosses 500 within weeks — at which point the "All" tab slows down and rows beyond 500 silently disappear (the dangerous half).

Scope

Server (this repo)

  • limit/offset (or cursor) on listRequests + REST query params; return total
  • Push the filters the client currently applies in memory down into engine queries: status, object, free-text (record title / requester / process label)
  • The known obstacle: pending_approvers is a CSV string and "my pending" matching is a post-filter in memory (acknowledged in the code comments). Pagination makes that incorrect — either push it down as a LIKE-composite, or (recommended) split approvers into a join table. The migration also fixes the long-standing indexing note on sys_approval_request ("the engine does a post-filter substring match per row").

Console (objectstack-ai/objectui)

  • Load-more / pager on the inbox tables; debounced server-side search
  • Keep the enriched display contract (record_title, payload_display, …) — enrichment is already batched per page server-side, so cost scales with page size

Trigger

Do this before any real tenant's request table reaches a few hundred rows, or as soon as the "All" tab is perceptibly slow. Recommend bundling the approver join-table migration into the same change — one migration solves both matching performance and pagination correctness.

References

  • Current implementation: listRequests in packages/plugins/plugin-approvals/src/approval-service.ts (limit 500, post-filters)
  • Index caveat: sys_approval_request.object.ts indexes comment

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions