What happened
Direct SQL fix to update_exclusions corrected the DB, but Redis still held stale data. Broccoli hits Redis first, never reached the DB, kept skipping 289 locations. The 2 locations edited via UI worked because UI calls invalidate cache automatically.
The rule
- API updates → cache invalidated automatically ✅
- Direct SQL updates → cache not invalidated — must clear manually ❌
Redis had no TTL — stale data lived forever until explicitly cleared.
Correct order for manual fixes
- Fix DB via SQL
- Clear Redis:
POST /locations/clear-cache - Re-run the sync
Debugging mental model
Always check all three layers — they can disagree:
API response ← Redis ← PostgreSQL
If API looks wrong but DB is correct, suspect cache.