super_cache
A production-grade, mobile-first LRU caching engine for Flutter and Dart.
Zero external dependencies. Batteries-included observability, TTL, memory pressure handling, and Clean Architecture integration out of the box.
Features
| Feature | Details |
|---|---|
| O(1) LRU | HashMap + manual doubly-linked list — correct and fast |
| TTL | Absolute or sliding; lazy expiration + background sweep |
| Capacity | Count-based (maxEntries) and bytes-based (maxBytes) |
| Observability | CacheMetrics snapshot and metricsStream broadcast |
| Layered cache | CacheOrchestrator L1→L2→L3 with automatic promotion |
| Repository pattern | CacheRepositoryMixin with stampede protection |
| Memory pressure | MemoryCachePressureWatcher (iOS/Android) |
| Debug UI | CacheDebugOverlay widget |
Installation
dependencies:
super_cache: ^1.0.0
For Flutter-specific features (memory pressure, debug overlay):
import 'package:super_cache/super_cache_flutter.dart';
For pure-Dart environments (tests, CLI):
import 'package:super_cache/super_cache.dart';
Quick start
In-memory LRU cache
import 'package:super_cache/super_cache.dart';
final cache = MemoryCache<String, User>(
maxEntries: 200,
defaultTTL: const Duration(minutes: 5),
);
cache.put('user_1', user);
final user = cache.get('user_1'); // null if expired or evicted
cache.dispose();
Layered cache (L1 memory + L3 disk)
import 'package:super_cache/super_cache.dart';
import 'package:super_cache_disk/super_cache_disk.dart';
final cache = CacheOrchestrator<String, Product>(
l1: MemoryCache(maxEntries: 100),
l3: DiskCache(
directory: cacheDir,
codec: JsonCacheCodec(
fromJson: Product.fromJson,
toJson: (p) => p.toJson(),
),
),
);
await (cache.l3 as DiskCache).initialize();
await cache.put('p_1', product);
final p = await cache.get('p_1'); // L1 hit on second access
Repository mixin
class UserRepository with CacheRepositoryMixin<String, User> {
@override
Cache<String, User> get cache => _cache;
final _cache = MemoryCache<String, User>(maxEntries: 200);
Future<User?> getUser(String id) => fetchWithCache(
id,
policy: const CacheAside(ttl: Duration(minutes: 5)),
onMiss: () => _api.fetchUser(id),
);
}
Concurrent calls for the same key while the cache is cold trigger only
one onMiss invocation — the second caller awaits the same Future.
Cache policies
| Policy | Description |
|---|---|
CacheAside |
Check cache; on miss call onMiss, store result. Default. |
WriteThrough |
Every write goes to both cache and source simultaneously. |
RefreshAhead |
Serve current (potentially stale) value while refreshing in background after refreshAfter elapses. |
TTL modes
// Absolute TTL (default): entry expires X seconds after put()
final cache = MemoryCache<String, String>(
defaultTTL: const Duration(minutes: 10),
);
// Sliding TTL: TTL resets on every successful get()
final sliding = MemoryCache<String, String>(
defaultTTL: const Duration(minutes: 10),
ttlMode: TTLMode.sliding,
);
Observability
// One-shot snapshot
final m = cache.metrics;
print('Hit rate: ${(m.hitRate * 100).toStringAsFixed(1)}%');
print('Entries: ${m.currentEntries} / ${m.hits + m.misses} requests');
// Live stream (emits on every sweep interval)
cache.metricsStream.listen((m) {
debugPrint('$m');
});
Memory pressure (Flutter)
import 'package:super_cache/super_cache_flutter.dart';
final cache = MemoryCache<String, Uint8List>(maxEntries: 500);
final watcher = MemoryCachePressureWatcher(cache: cache);
// WidgetsBinding registers automatically — no extra setup needed.
// Dispose when done:
watcher.dispose();
On moderate memory pressure: evicts the least-recently-used 20% of entries. On critical pressure: evicts 50%.
Packages in this family
| Package | Purpose |
|---|---|
super_cache |
Core LRU engine (this package) |
super_cache_secure |
AES-256-GCM encrypted in-memory cache |
super_cache_disk |
Persistent file-based cache with SHA-256 integrity |
super_cache_testing |
FakeCache + ManualClock for unit tests |
Libraries
- super_cache
- super_cache — Production-grade mobile-first caching engine for Flutter.
- super_cache_flutter
- Flutter-specific extensions for super_cache.