# ICOMAN performance decisions

Target: support 100,000+ members without adding infrastructure that the current application does not need.

## Query and database decisions

- Member identity lookup remains a unique indexed lookup. Public QR/barcode verification is deliberately uncached so card/token revocation is immediately authoritative.
- Added composite indexes for state/region/category member-status counts, application status queues, verification time windows, bulk-import row processing, and audit-log recency.
- All listing endpoints use pagination. Card templates now use 30-item cursor-free simple pagination; organization, BOT review, and imports were already paginated.
- Dashboard keeps aggregate queries in SQL and uses subqueries rather than loading member IDs into PHP. It is not cached because operators need current approval/card state.
- Reports use a user-and-role-scoped 60-second cache. This is a safe bounded staleness tradeoff for expensive aggregate pages; it neither changes permissions nor caches public verification.

## Expensive work

- Bulk imports already run through `ProcessBulkImport` and process rows with a cursor to avoid loading whole imports into memory.
- SVG/PDF-like card face rendering now runs through `GenerateIdentityCard`; the HTTP request queues it and returns immediately.
- Production should use a durable queue backend. The `sync` driver remains suitable for local development and tests.

## Deliberately deferred

- No search system is exposed today; do not add a search index until a concrete member-search route and ranking requirements exist.
- No separate cache service, read replica, or image-processing service is required at this stage. Reassess using production query latency and queue depth telemetry.
- API member responses are one-record policy-protected lookups, not collection endpoints; pagination is therefore not applicable.
