Opinionated Storage Configuration
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
🎯 Opinionated Storage Configuration - The One Perfect Setup
Date: October 6, 2025
Philosophy: Simplicity over flexibility. Optimal over configurable.
🤔 The Problem with "Strategies"
Original Approach (Overcomplicated):
// ❌ TOO MANY OPTIONS!
provideGgStorage({
strategy: 'speed' | 'balanced' | 'durable', // Which one???
performance: {
adaptiveStrategy: true, // More options!
redundancy: true, // Even more options!
}
})
Problems:
- 🤷 Users don't know which strategy to choose
- 📚 Requires reading complex documentation
- 🐛 Wrong choice = poor performance
- 🔄 Multiple adapters created (localStorage + Dexie)
- 💾 Data ends up in BOTH places (defeating the purpose!)
✅ The Solution: One Perfect Configuration
Our Philosophy:
"For Flash Persistence and large capacity storage, there's only ONE correct answer: Dexie (IndexedDB) ONLY."
Why This is Right:
IndexedDB is objectively better for our use case:
- ✅ 50MB-1GB+ capacity (vs 5-10MB localStorage)
- ✅ Structured data (vs string-only)
- ✅ Cross-tab sync built-in
- ✅ Async (non-blocking)
- ✅ Fast (especially with micro-cache)
Micro-cache solves the "localStorage speed advantage":
- ✅ 256KB in-memory cache
- ✅ 0.00ms reads (instant!)
- ✅ No need for localStorage sync access
Simplicity wins:
- ✅ No confusing options
- ✅ No wrong choices possible
- ✅ Optimal by default
- ✅ One adapter created (Dexie only)
🎯 The Perfect Configuration
For gograb-space (and all apps):
// apps/gograb-space/src/main.ts
provideGgStorage({
namespace: 'gograb-space',
// 🎯 FORCE Dexie only (no localStorage adapter created)
adapter: 'dexie', // ⚠️ CRITICAL: Only create Dexie adapter!
// 📦 Cache configuration
cache: { maxItems: 500, ttlMs: 300_000 },
// 🚀 Performance optimization
performance: {
adaptiveStrategy: false, // We know Dexie is best, no need to adapt
redundancy: false, // No localStorage mirroring
monitoring: true, // Keep performance tracking
microCacheBudget: 256 * 1024, // 256KB micro-cache for instant reads
microCacheMaxEntrySize: 32 * 1024,
allowLargeMicroCacheEntries: true
}
})
What This Does:
App Startup:
└─► GgStorage.create({ adapter: 'dexie' })
└─► ONLY creates Dexie adapter ✅
└─► NO localStorage adapter ✅
└─► Creates micro-cache (memory) ✅
Write Operation:
└─► Dexie (IndexedDB) ONLY ✅
└─► Micro-cache update ✅
└─► localStorage NEVER TOUCHED ✅
Read Operation:
1. Check micro-cache (0.00ms) ✅
2. If miss: Read from Dexie (~2ms) ✅
3. Update micro-cache ✅
4. localStorage NEVER TOUCHED ✅
🚫 When NOT to Use This
Edge Cases (Rare):
Legacy browser support (IE11, old mobile browsers)
- Solution: Don't support them. It's 2025.
Testing environments that block IndexedDB
- Solution: Fix your test environment
Critical auth tokens that MUST be synchronously accessible
- Solution: Use a separate, dedicated localStorage key (not via GgStorage)
Extremely small data (< 1KB) that's accessed every frame
- Solution: Keep in component state/signal, not storage
For These Cases:
Use localStorage directly (don't go through GgStorage):
// For tiny, critical, sync-required data ONLY
localStorage.setItem('auth-token', token);
// Everything else goes through GgStorage (Dexie only)
await storage.put('user-preferences', prefs);
📊 Performance Comparison
Before (Multiple Adapters):
| Metric | Value |
|---|---|
| Adapters Created | 2 (Dexie + localStorage) |
| Writes | 2 locations (duplicated!) |
| Effective Capacity | 5-10MB (localStorage limit) |
| localStorage Usage | Full data objects |
| Confusion | High (which adapter is used?) |
After (Dexie Only):
| Metric | Value |
|---|---|
| Adapters Created | 1 (Dexie only) |
| Writes | 1 location (IndexedDB) |
| Effective Capacity | 50MB-1GB+ |
| localStorage Usage | ZERO |
| Confusion | ZERO (obvious what's happening) |
🎓 Answering Your Questions
Q: "Why have strategies at all?"
A: You're right! For our use case (Flash Persistence + large capacity), we don't need strategies. We keep them only for:
- Backward compatibility with existing code
- Framework flexibility (other projects might have different needs)
- But we recommend ONE configuration for all new projects
Q: "Isn't having multiple strategies making our platform less optimal?"
A: Absolutely YES! That's why we're moving to opinionated configuration:
- ✅ One recommended setup
- ✅ Optimal by default
- ✅ No confusing options
- ✅ Can't choose wrong
Q: "Are there use cases where we need redundant data?"
A: Rarely. The only legitimate case is:
- Extreme reliability requirements where you want data in multiple places
- Cost: Double storage usage + double write time
- Better solution: Use Dexie's built-in transaction system (already reliable)
For 99% of apps: Redundancy is wasteful and unnecessary.
🔮 Future Direction
Vision: Zero Configuration
Eventually, we should get to:
// The ONLY configuration needed:
providers: [
provideStorageRegistry(),
provideOptimalStorage('gograb-space'), // ✨ That's it!
provideAutoFlashPersistence()
]
Under the hood:
- ✅ Auto-detects Dexie support
- ✅ Creates Dexie adapter only
- ✅ Configures optimal micro-cache
- ✅ Registers with Storage Registry
- ✅ Flash Persistence works automatically
No strategies. No options. Just works perfectly.
📝 Migration from Old Config
If You Have This:
// ❌ Old (overcomplicated)
provideGgStorage({
strategy: 'balanced', // Remove
performance: {
redundancy: true, // Remove
adaptiveStrategy: true // Remove
}
})
Change to This:
// ✅ New (opinionated)
provideGgStorage({
adapter: 'dexie', // ONLY create Dexie
performance: {
redundancy: false,
adaptiveStrategy: false,
microCacheBudget: 256 * 1024 // Enough for fast reads
}
})
Result:
- ✅ localStorage will be EMPTY
- ✅ All data in IndexedDB only
- ✅ Same read performance (micro-cache)
- ✅ 10-200x capacity increase
- ✅ No confusion about which adapter is used
✅ Verification
After Refresh:
Console:
🎯 CREATING NEW adapter: dexie for namespace: gograb-space
✅ GgStorage initialized with Dexie only
Should NOT see:
🎯 CREATING NEW adapter: localStorage ← Should NOT appear!
DevTools → Application:
IndexedDB:
- ✅ Database:
gograb-spaceStorageDb - ✅ All your data here
- ✅ Database:
localStorage:
- ✅ Should be COMPLETELY EMPTY
- ✅ No
gg-boot:*keys - ✅ No
flash:*keys - ✅ No metadata objects
🎯 Key Takeaways
Simplicity Wins
- One perfect configuration > many confusing options
- Optimal by default > flexible but error-prone
Dexie is the Answer
- For Flash Persistence: Always Dexie, never localStorage
- Micro-cache solves speed concerns
- No need for localStorage at all
Remove Redundancy
- Wastes storage
- Complicates architecture
- No real benefit for our use case
Be Opinionated
- Guide users to the right choice
- Don't offer bad options
- Make it hard to do the wrong thing
📚 Related Documentation
storage-capacity-strategy.md- Why we disabled redundancyTODAYS_IMPROVEMENTS.md- Complete fix historyFIXES_APPLIED.md- All fixes applied today
Status: ✅ PRODUCTION READY 🎉
Philosophy: "The best configuration is the one you don't have to think about." 🎯