Best Practices
Use ReadMeter to spot risky patterns early. These practices help reduce Firestore read costs.
1. Watch the widget during development
Keep the ReadMeter widget visible while you build. When you see "Read Source" or high read counts, that's a signal to optimize before traffic scales.
2. Heed the risk levels
ReadMeter uses simple thresholds:
- Safe — ≤30 reads per page load
- Scales with traffic — 31–100 reads
- High risk — >100 reads
These are intentionally conservative. They exist to change behavior early, not to be perfectly accurate.
3. Client-side filtering over multiple queries
Fetch once, filter many times:
// ❌ Bad: Multiple queries
const admins = await getDocs(query(usersRef, where('role', '==', 'admin')))
const users = await getDocs(query(usersRef, where('role', '==', 'user')))
// ✅ Good: Fetch once, filter client-side
const allUsers = await getDocs(collection(db, 'users'))
const admins = allUsers.docs.filter(d => d.data().role === 'admin')
const users = allUsers.docs.filter(d => d.data().role === 'user')4. Cache frequently accessed data
If the same collection is read on multiple pages or components, cache it. ReadMeter will show repeated reads — that's your cue to add a cache layer.
5. Avoid queries in render loops
If a query runs on every render, ReadMeter will show high execution counts. Use memoization, move the fetch to a parent, or use a data-fetching library that deduplicates.
6. Use pagination for large lists
Don't fetch entire collections when you only need a subset. Use limit() and cursor-based pagination.
7. Real-time listeners count on initial load
onSnapshot reads everything on first attach. If you have many listeners, the initial page load can be expensive. Consider batching or lazy-loading listeners.
Common pitfalls
- Fetching all users for simple role checks
- Querying the same collection from multiple components
- No cache expiration (stale data)
- Processing all documents in scheduled functions