Performance Anti-Patterns Reference
N+1 Query Problem
The N+1 problem occurs when code executes N additional queries to fetch related data for N items from an initial query.
Identification:
- •Queries inside loops
- •Lazy loading of associations during iteration
- •GraphQL resolvers fetching per-item
Fix Strategies:
- •Eager Loading: Load related data in initial query
- •Batching: Collect IDs, fetch all at once
- •DataLoader: For GraphQL, batch and cache per-request
- •Denormalization: Store computed/related data together
Severity: HIGH - Scales linearly with data size, causes exponential slowdown
Over-Fetching
Retrieving more data than needed from API or database.
Identification:
- •SELECT * queries
- •API endpoints returning full objects
- •No field selection support
- •Loading nested relations by default
Fix Strategies:
- •Field Selection: Only query needed columns
- •Sparse Fieldsets: Support
?fields=id,nameparameter - •GraphQL: Let clients specify exact fields
- •DTOs: Map to response-specific objects
Severity: MEDIUM - Increases bandwidth, memory, serialization time
Under-Fetching
Requiring multiple requests to get needed data.
Identification:
- •Waterfall requests (request depends on previous)
- •Multiple endpoints for related data
- •No include/expand support
Fix Strategies:
- •Compound Endpoints:
/users?include=orders - •GraphQL: Single query for nested data
- •BFF Pattern: Backend aggregates for frontend
- •Parallel Requests: When dependencies allow
Severity: MEDIUM - Increases latency, connection overhead
Missing Pagination
Returning unbounded result sets.
Identification:
- •List endpoints without limit
- •
findAll()without pagination - •No cursor for large datasets
Fix Strategies:
- •Offset Pagination:
?page=1&limit=20 - •Cursor Pagination:
?cursor=abc&limit=20(better for large sets) - •Default Limits: Always apply max limit server-side
- •Streaming: For very large exports
Severity: HIGH - Can crash server/client with large data
Inefficient Algorithms
O(n²) or worse complexity where better solutions exist.
Identification:
- •Nested loops on collections
- •Repeated array.find/includes in loops
- •String concatenation in loops
- •Sort inside loops
Fix Strategies:
- •Use Maps/Sets: O(1) lookup instead of O(n)
- •Single Pass: Combine operations
- •Pre-compute: Calculate once, reuse
- •Better Algorithms: Binary search for sorted data
Severity: HIGH - Becomes unusable with large data
Unnecessary Re-renders (Frontend)
Components re-rendering when their output hasn't changed.
Identification:
- •Inline objects/arrays in JSX
- •Inline function handlers
- •Missing React.memo/useMemo/useCallback
- •Context changes affecting all consumers
Fix Strategies:
- •Memoization: React.memo for components
- •Stable References: useMemo for objects, useCallback for functions
- •Context Splitting: Separate frequently-changing state
- •Selectors: Only subscribe to needed state slices
Severity: MEDIUM-HIGH - Causes janky UI, especially on lists
Sequential Async Operations
Running async operations one-by-one when parallel is possible.
Identification:
- •Sequential await statements
- •Waterfall promises
- •Loop with await inside
Fix Strategies:
- •Promise.all: Run independent operations in parallel
- •Promise.allSettled: When some can fail
- •Batching: Group operations efficiently
- •Pipelining: Stream processing
Severity: MEDIUM - Multiplies latency
Quick Reference by Layer
Database
| Issue | Detect | Fix |
|---|---|---|
| N+1 queries | Query in loop | Eager load / batch |
| Missing index | Slow WHERE/JOIN | Add index |
| SELECT * | No column list | Specify columns |
| No LIMIT | Unbounded query | Add pagination |
Backend
| Issue | Detect | Fix |
|---|---|---|
| O(n²) loop | Nested iteration | Use Set/Map |
| Sequential await | await in sequence | Promise.all |
| Sync I/O | fs.readFileSync | Use async version |
| No caching | Repeated computation | Memoize |
Frontend
| Issue | Detect | Fix |
|---|---|---|
| Re-renders | Inline objects/functions | Memoize |
| Bundle size | Large imports | Tree-shake/split |
| Memory leak | No cleanup | useEffect cleanup |
| Layout thrash | Read+write DOM | Batch DOM ops |
API
| Issue | Detect | Fix |
|---|---|---|
| Over-fetching | All fields returned | Field selection |
| Under-fetching | Multiple requests | Include/expand |
| No pagination | Unbounded lists | Add limit/cursor |
| N+1 calls | Fetch in loop | Batch endpoint |