Performance Audit Findings
Full performance audit conducted March 4, 2026 across three areas: database queries, bundle/rendering, and API routes.
Critical Issues
1. Cart Page God Component
src/app/cart/page.tsx is 2,677 lines with 27 useState hooks. Every keystroke re-renders the entire page including all cart items, payment forms, and address inputs.
Impact: Severe input lag, excessive re-renders, poor mobile performance. Remediation: Split into sub-components (CartItems, PaymentSection, AddressCard, OrderSummary). Extract state into focused custom hooks.
2. Manager Dashboard Sequential API Calls
OrdersDashboardContent.tsx makes 8 sequential API calls (one per order status: pending, confirmed, preparing, ready, picked_up, delivered, cancelled, failed).
Impact: Dashboard load time ~2-4s on good connection. Each call waits for the previous. Remediation: Combine into single endpoint with status filter, or parallelize with Promise.all.
3. Auth Cost Per Request
Every authenticated request costs 2 DB roundtrips: JWT verification + user profile lookup from users table.
Impact: Adds ~50-100ms latency to every API call. Remediation: Cache user profile in JWT claims or use short-lived memory cache.
4. Image Optimization Disabled
next.config.ts has unoptimized: true on images. All images served at original resolution.
Impact: Menu pages load 5-10MB of images on mobile. Critical for Honduras bandwidth.
Remediation: Remove unoptimized: true, configure Next.js image optimization with Cloudflare R2 loader.
High Issues
5. Order Detail Endpoint — Sequential Queries
Order detail API route makes 8-9 sequential DB queries: order, items, restaurant, customer, driver, address, payment, status history, ratings.
Impact: Single order detail takes 400-800ms. Remediation: Parallelize independent queries with Promise.all or use Supabase joins.
6. SWR Aggressive Revalidation
Global SWR config has revalidateOnFocus: true. Every tab switch triggers refetches across all cached endpoints.
Impact: Unnecessary network traffic, Supabase quota burn, UI flicker on tab return.
Remediation: Disable revalidateOnFocus globally, use revalidateOnFocus selectively where freshness matters.
7. No Response Caching
Zero caching headers on any API response. Static data (restaurant info, menu items, categories) re-fetched on every request.
Impact: Redundant DB queries, higher Supabase usage, slower page loads. Remediation: Add Cache-Control headers for static/semi-static data (restaurants: 5min, menu: 2min).
8. Admin Drivers Endpoint — No Pagination
/api/admin/drivers returns all drivers with no pagination. Full table scan every request.
Impact: Grows linearly with driver count. Will degrade as platform scales. Remediation: Add limit/offset pagination, default 50 per page.
9. SELECT * Everywhere
All Supabase queries use select("*") instead of specific columns. Fetches all columns including unused ones.
Impact: Larger payloads, slower serialization, unnecessary data transfer. Remediation: Replace with specific column selections per query.
Optimizations Implemented (March 4)
Completed Fixes
| Fix | Description | Files |
|---|---|---|
| Firebase dead code removal | Deleted unused firebase.ts and converters.ts |
2 files deleted |
| CartContext memoization | Wrapped 10 handlers in useCallback, context value in useMemo | CartContext.tsx |
| Visibility-aware polling | Created useVisibilityAwareInterval hook — pauses intervals when tab backgrounded |
6 components updated |
| Blob URL memory leaks | Restaurant/menu image uploads now revoke old blob URLs | ManagerConsole.tsx |
| Rogue local fetcher | Replaced raw fetch() with shared apiClient fetcher | restaurants/page.tsx |
useVisibilityAwareInterval Applied To
- Header.tsx (30s active order badge)
- admin/orders/page.tsx (15s orders)
- OrdersDashboardContent.tsx (15s orders)
- ManagerConsole.tsx (15-30s auto-refresh)
- ManagerNotificationListener.tsx (5s localStorage + 60s orders)
- orders/page.tsx (30s polling)