Engineering: Capping Unbounded Sub-list Queries (PERF-15)
Engineering: Capping Unbounded Sub-list Queries (PERF-15)
Release: v1.0.84
Audit finding: PERF-15
Background
A performance audit identified 14 database sub-queries across the property, owner, maintenance, and compliance routers that returned unlimited rows. In a production environment serving multi-unit residential developments, certain data sets — ownership histories, service charge demands, compliance certificates, maintenance activity notes — grow continuously over the lifetime of a development. Returning every row on every request is unsustainable at scale.
This release applies targeted row limits to all affected queries and upgrades listBuildings to proper cursor pagination.
What Was Fixed
listBuildings — Cursor Pagination
Previously listBuildings returned all buildings for a development with no limit. It now uses the shared paginationInput / paginatedResult helpers, providing cursor-based pagination with a default page size of 20.
// Input now accepts cursor pagination params alongside developmentId
listBuildings.useQuery({ developmentId, limit: 20, cursor: undefined })
Callers that pass only { developmentId } continue to work — paginationInput defaults are applied automatically.
Detail-view Sub-lists — Hard Caps
Sub-lists embedded in detail-view responses (ownerships, demands, notes, certificates) are now capped. These views are intended for at-a-glance information; full paginated histories are available through dedicated list endpoints.
| Endpoint | Sub-list | Cap |
|---|---|---|
property.getUnit | Ownership history | 20 |
property.getOwner | Owned units | 20 |
property.getDevelopment | Buildings | 100 |
owner.getById | Ownerships | 20 |
owner.getById | Service charge demands | 20 |
owner.getById | Portal tokens | 10 |
owner.getPortalData | Demands | 20 |
owner.getPortalData | Payments | 20 |
owner.getPortalData | Owned units | 50 |
maintenance.getRequest | Activity notes | 50 |
compliance.getObligation | Certificates | 20 |
compliance.getObligation | Event history | 20 |
getUnitOwnershipHistory — Configurable Limit
This dedicated history endpoint previously returned all records. It now accepts a limit parameter (integer, 1–200, default 50).
// Fetch up to 100 ownership records for a unit
ownerRouter.getUnitOwnershipHistory.useQuery({ unitId, limit: 100 })
Callers that do not pass limit receive the first 50 records.
UI Guidance
Where a detail view previously displayed a complete unbounded list, consider adding a "View all" affordance that links to the appropriate paginated list endpoint:
- Ownership history →
owner.getUnitOwnershipHistory - Full owner list for a unit →
property.listOwners/owner.getById - Buildings in a development →
property.listBuildings(now paginated)
For maintenance.getRequest, if a request has accumulated more than 50 activity notes, surface a "View all notes" link; the cap is documented in the API comment.
No Breaking Changes
All existing callers are compatible with the new defaults:
- Sub-list caps match or exceed the row counts typical of production data at the time of the audit.
listBuildingsdefaults apply transparently to callers that do not supply pagination parameters.getUnitOwnershipHistorydefault of 50 matches prior typical result sizes.