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:

  1. 🤷 Users don't know which strategy to choose
  2. 📚 Requires reading complex documentation
  3. 🐛 Wrong choice = poor performance
  4. 🔄 Multiple adapters created (localStorage + Dexie)
  5. 💾 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:

  1. 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)
  2. Micro-cache solves the "localStorage speed advantage":

    • ✅ 256KB in-memory cache
    • ✅ 0.00ms reads (instant!)
    • ✅ No need for localStorage sync access
  3. 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):

  1. Legacy browser support (IE11, old mobile browsers)

    • Solution: Don't support them. It's 2025.
  2. Testing environments that block IndexedDB

    • Solution: Fix your test environment
  3. Critical auth tokens that MUST be synchronously accessible

    • Solution: Use a separate, dedicated localStorage key (not via GgStorage)
  4. 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:

  1. Backward compatibility with existing code
  2. Framework flexibility (other projects might have different needs)
  3. 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:

Q: "Are there use cases where we need redundant data?"

A: Rarely. The only legitimate case is:

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:

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:

  1. ✅ localStorage will be EMPTY
  2. ✅ All data in IndexedDB only
  3. ✅ Same read performance (micro-cache)
  4. ✅ 10-200x capacity increase
  5. ✅ 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:

  1. IndexedDB:

    • ✅ Database: gograb-spaceStorageDb
    • ✅ All your data here
  2. localStorage:

    • ✅ Should be COMPLETELY EMPTY
    • ✅ No gg-boot:* keys
    • ✅ No flash:* keys
    • ✅ No metadata objects

🎯 Key Takeaways

  1. Simplicity Wins

    • One perfect configuration > many confusing options
    • Optimal by default > flexible but error-prone
  2. Dexie is the Answer

    • For Flash Persistence: Always Dexie, never localStorage
    • Micro-cache solves speed concerns
    • No need for localStorage at all
  3. Remove Redundancy

    • Wastes storage
    • Complicates architecture
    • No real benefit for our use case
  4. Be Opinionated

    • Guide users to the right choice
    • Don't offer bad options
    • Make it hard to do the wrong thing

📚 Related Documentation


Status: ✅ PRODUCTION READY 🎉

Philosophy: "The best configuration is the one you don't have to think about." 🎯