Cache Patterns

This page outlines common caching patterns with Morphium and when to use them.

  1. Read‑through entity cache (default)
  • Use @Cache on entities to enable read cache for queries and ID cache
  • Choose a clear strategy that matches your write rate and consistency needs
@Cache(timeout = 30_000, clearOnWrite = true, strategy = Cache.ClearStrategy.LRU, syncCache = Cache.SyncCacheStrategy.CLEAR_TYPE_CACHE)
public class Product { ... }

When to use

  • Most read‑heavy entities, where occasional stale reads for up to the TTL are acceptable
  1. Precise invalidation per entity (remove or update)
  • Reduce blast radius on writes by removing/updating only affected IDs instead of clearing the whole type cache
@Cache(timeout = 60_000, clearOnWrite = true, syncCache = Cache.SyncCacheStrategy.REMOVE_ENTRY_FROM_TYPE_CACHE)
public class User { ... }

or

@Cache(timeout = 60_000, clearOnWrite = true, syncCache = Cache.SyncCacheStrategy.UPDATE_ENTRY)
public class User { ... }

Notes

  • With UPDATE_ENTRY, other nodes re‑read the updated document (slightly higher cost, but fewer cache misses)
  1. Cluster‑wide synchronization via messaging
  • Ensure every node runs messaging and attach a MessagingCacheSynchronizer
MorphiumMessaging messaging = morphium.createMessaging();
messaging.start();
new MessagingCacheSynchronizer(messaging, morphium);

When to use

  • Multi‑node deployments that need consistent caches after writes
  1. TTL tuning and hot‑set sizing
  • Keep @Cache.timeout small enough to minimize staleness, large enough to reduce DB load
  • Use maxEntries and strategy to control memory use and eviction behavior
@Cache(timeout = 15_000, maxEntries = 50_000, strategy = Cache.ClearStrategy.LRU)
public class Article { ... }
  1. JCache integration and layering
  • Use MorphiumCacheJCacheImpl to adopt javax.cache
  • Optionally back it with an external provider for cross‑JVM cache layers
MorphiumCacheJCacheImpl jcache = new MorphiumCacheJCacheImpl();
cfg.cacheSettings().setCache(jcache);
  1. Avoiding cache stampede
  • For heavy queries, consider:
    • Pre‑warming popular keys at startup
    • Adding small jitter to TTL at application level if you implement explicit invalidation
    • Using UPDATE_ENTRY to keep hot IDs fresh without clearing type cache
  1. Eventual vs strong consistency
  • Read‑through caching is eventually consistent between nodes
  • To minimize staleness:
    • Use smaller TTLs
    • Prefer REMOVE_ENTRY_FROM_TYPE_CACHE or UPDATE_ENTRY
    • Ensure messaging is available and responsive (replica set + change streams is preferred)
  1. Batching and write buffering
  • Global write buffering and async writes reduce DB pressure under load
cfg.cacheSettings().setAsyncWritesEnabled(true);
cfg.cacheSettings().setBufferedWritesEnabled(true);

Trade‑off

  • Buffering can delay writes; choose TTLs and cache sync strategies accordingly
  1. Manual controls for maintenance
// Clear one type
morphium.clearCachefor(Product.class);
// Clear all types on all nodes
new MessagingCacheSynchronizer(messaging, morphium).sendClearAllMessage("maintenance");
  1. Query‑result cache keys
  • Morphium computes a deterministic key for queries (criteria + sort + projection + paging)
  • Prefer projections to keep cached result documents small

See also

← Back to Documentation Hub