cacherine
cacherine is a simple and flexible memory cache library for Dart. It provides caching algorithms such as FIFO, LRU, MRU, LFU, and TTL-based expiry. Both single-threaded and async-enabled versions are available to handle different usage scenarios.
If you want to choose the best cache algorithm for your app, you can use MonitoredCache in your development environment. It helps you monitor performance metrics (such as hit/miss rates, latency, and eviction alerts) so you can make data-driven decisions and optimize the algorithm you use.
Why cacherine?
Dart/Flutter does not have a built-in caching solution similar to NSCache in Swift.
cacherine was created to provide a lightweight and flexible in-memory cache with common caching strategies like FIFO, LRU, MRU, and LFU.
Whether you need a simple single-threaded cache or an async-compatible solution for concurrent environments, cacherine offers an easy-to-use API.
Features
- FIFO (First In, First Out) — Learn more
- EphemeralFIFO (FIFO-based cache where keys are removed after being accessed) — Learn more
- LRU (Least Recently Used) — Learn more
- MRU (Most Recently Used) — Learn more
- LFU (Least Frequently Used) — Learn more
- TTL (Time-To-Live — entries auto-expire after a configurable duration; optional per-entry TTL override and background sweep) — Learn more
- MonitoredCache (Includes performance monitoring with hit/miss rates, latency, and eviction alerts) — Learn more
- CacheStatsDashboard (Wraps a MonitoredCache's metrics to provide point-in-time snapshots and periodic streams;
formatDashboard()renders a Unicode terminal panel) - Simple versions (e.g., SimpleFIFOCache) for single-threaded usage, and standard versions for multi-threaded environments
Installation
Check the latest version on pub.dev and add it to your pubspec.yaml:
dependencies:
cacherine: ^latest_version
Then, run the following command in your terminal:
dart pub get
Usage
Basic Usage (Single-threaded)
import 'package:cacherine/cacherine.dart';
void main() {
final cache = SimpleFIFOCache<String, String>(maxSize: 5);
cache.set('key1', 'value1');
print(cache.get('key1')); // 'value1'
}
Async Usage (Async support)
import 'package:cacherine/cacherine.dart';
void main() async {
final cache = FIFOCache<String, String>(maxSize: 5);
await cache.set('key1', 'value1');
print(await cache.get('key1')); // 'value1'
}
TTL Usage
Entries expire automatically once their TTL elapses. Use ttl: on individual set() calls to override the global default for a single entry.
import 'package:cacherine/cacherine.dart';
void main() async {
final cache = TTLCache<String, String>(
ttl: const Duration(minutes: 5), // global default
maxSize: 100, // optional capacity limit
sweepInterval: const Duration(minutes: 1), // optional background sweep
);
await cache.set('token', 'abc123'); // expires in 5 min
await cache.set('rate', '42', ttl: Duration(seconds: 30)); // expires in 30 s
print(await cache.get('token')); // 'abc123' (if within TTL)
cache.dispose(); // cancel background sweep timer when done
}
Monitoring Usage
If you want to monitor the performance of your cache and optimize the algorithm, use MonitoredCache. Learn more about MonitoredCache and performance monitoring.
Stats Dashboard Usage
CacheStatsDashboard wraps any CacheMetrics instance (exposed by MonitoredCache variants) to give you typed snapshots and a periodic stream. Use formatDashboard() to render a human-readable terminal panel.
import 'package:cacherine/cacherine.dart';
void main() async {
final cache = MonitoredLRUCache<String, String>(maxSize: 100);
// warm up the cache
await cache.set('key', 'value');
await cache.get('key');
// one-shot snapshot over a 1-minute eviction window
final dashboard = CacheStatsDashboard(cache.metrics);
final snap = dashboard.snapshot(const Duration(minutes: 1));
print(formatDashboard(snap));
// ┌─── Cacherine Dashboard Snapshot ─────────────────────────────┐
// │ Captured at: 2026-05-15 12:00:00 │
// ├───────────────────────────────────────────────────────────────┤
// │ Traffic: 1 request │
// │ Hit Rate: 100.0% [████████████████████] │
// ├───────────────────────────────────────────────────────────────┤
// │ Latency: P50: 12µs / P95: 12µs / P99: 12µs │
// │ Evictions: 0 / min │
// └───────────────────────────────────────────────────────────────┘
// periodic stream — emits every 5 seconds
final sub = dashboard
.stream(const Duration(minutes: 1), const Duration(seconds: 5))
.listen((s) => print(formatDashboard(s)));
await Future<void>.delayed(const Duration(seconds: 15));
await sub.cancel();
cache.dispose();
}
API Reference
-
FIFOCache<K, V>: FIFO-based cache
-
EphemeralFIFOCache<K, V>: FIFO-based cache where the key is removed after being accessed (One-Time Read Cache)
-
LRUCache<K, V>: Cache that removes the least recently used items
-
MRUCache<K, V>: Cache that removes the most recently used items
-
LFUCache<K, V>: Cache that removes the least frequently used items
-
TTLCache<K, V>: Cache with time-based expiry; global TTL with optional per-entry override, lazy eviction, optional background sweep, and optional capacity limit
-
MonitoredFIFOCache<K, V>: FIFO-based cache with monitoring
-
MonitoredEphemeralFIFOCache<K, V>: Ephemeral FIFO cache with monitoring
-
MonitoredLRUCache<K, V>: LRU-based cache with monitoring
-
MonitoredMRUCache<K, V>: MRU-based cache with monitoring
-
MonitoredLFUCache<K, V>: LFU-based cache with monitoring
-
CacheStatsDashboard: Wraps
CacheMetricsto providesnapshot(Duration window)andstream(Duration window, Duration interval) -
DashboardSnapshot: Immutable point-in-time snapshot (hitRate, missRate, latency percentiles, evictionsPerMinute, totalRequests, capturedAt)
-
formatDashboard(): Renders a
DashboardSnapshotas a Unicode box-drawing terminal panel
Contributing
Contributions are welcome! If you find a bug, have a feature request, or want to improve the code, feel free to open an issue or submit a pull request.
How to Contribute
- Fork the repository and create a new branch.
- Make your changes and write tests if necessary.
- Ensure the code passes all checks (
dart analyze,dart test). - Open a pull request and describe your changes.
For major changes, please open an issue first to discuss your proposal.
We appreciate your support in making cacherine better! 🚀
Changelog
All notable changes to this project will be documented in the CHANGELOG file.
See the full changelog here.
License
This project is licensed under the MIT License - see the LICENSE file for details.