MicroCache Large Entry Fix - Storage System Intelligence Enhancement

Fix for MicroCache 'Entry too large' warning spam when storing large NGXS state data

🧠 MicroCache Large Entry Fix

Session: gspace-2.1
Date: January 7, 2026
Status: ✅ Complete
Confidence: 98%


📋 Problem Statement

The console was being spammed with warnings:

micro-cache.ts:124 MicroCache: Entry too large for key pages: 227484 bytes (max: 102400 bytes)

This warning appeared frequently because:

  1. Large NGXS state data (pages, widgets, editor) was ~227KB
  2. MicroCache is designed for tiny data (< 8KB by default)
  3. A code path was ignoring the policy engine's decision entirely

🔍 Root Cause Analysis

The Policy Engine Already Does Size Checks!

In policy-engine.ts, the policy engine checks:

const isSmall = size < 8 * 1024; // 8KB

const useMicroCache = strategy === 'speed' &&
                     isSmall &&  // ← ALREADY CHECKED!
                     (isCritical || isUserPref) &&
                     capabilities.localStorage;

const redundancy = {
  localStorage: (isCritical || isUserPref) && isSmall && capabilities.localStorage
  //                                          ↑ ALREADY CHECKED!
};

The Actual Bug

The problem was at lines 465-471 in gg-storage.ts:

// THE BUG - This code was ignoring the policy decision!
const shouldUpdateMicroCache = !key.toString().startsWith('flash:');
if (primarySuccess && shouldUpdateMicroCache) {
  this.microCache.set(key, value, decision.ttlMs);  // WROTE ALL DATA!
}

This was writing ALL successful non-flash writes to MicroCache, regardless of:


✅ Proper Solution (Refactored)

Trust the Policy Engine

Instead of adding duplicate size checks, we trust the policy engine which already validates everything:

// 2. Micro-cache (localStorage) for fast access
// Trust the policy engine - it already checked size, key type, and strategy
const shouldUseMicroCache = decision.target.localStorage === 'micro' && 
                             !key.toString().startsWith('flash:');
if (shouldUseMicroCache) {
  this.microCache.set(key, value, decision.ttlMs);
}

// 6. Redundancy writes for critical data
// Only write if policy decided AND we didn't already write above
if (primarySuccess && decision.redundancy.localStorage && !shouldUseMicroCache && !key.toString().startsWith('flash:')) {
  this.microCache.set(key, value, decision.ttlMs);
}

What Was Removed

MicroCache Warning (Kept)

Made the warning conditional on debug flag (this part is still valid):

if (entrySize > this.maxEntrySize) {
  if (typeof window !== 'undefined' && (window as any).__STORAGE_DEBUG__) {
    console.debug(`MicroCache: Skipping large entry "${key}": ${Math.round(entrySize / 1024)}KB`);
  }
  return false;
}

📊 Before vs After

Before (My Initial Fix - Band-Aid)

Policy Engine → makes decision → gg-storage ignores it → adds helper to re-check
                                                          ↑ REDUNDANT

After (Proper Fix)

Policy Engine → makes decision → gg-storage trusts it
                ↑ ALREADY VALIDATES SIZE, KEY TYPE, STRATEGY

📁 Files Modified

File Changes
gg-storage.ts Removed buggy cache-update block, trust policy engine
micro-cache.ts Made warning conditional on __STORAGE_DEBUG__ flag

🎯 Result


📚 Lesson Learned

Don't add layers on top of layers. Find the root cause.

The policy engine was doing its job correctly. The bug was code that bypassed it entirely. The fix is to remove the bypass, not to add another layer of validation.


📚 Related Documentation


Decision Logged: dev_1767824909021_g8khy4x (initial), refactored after self-review
MCP Confidence: 98%
Total Time: ~45 minutes (including self-critique and refactor)