@matteuccimarco/slim-redis
v0.1.0
Published
Redis client with automatic SLIM compression for JSON values - reduce memory usage by 40-50%
Downloads
102
Maintainers
Readme
@matteuccimarco/slim-redis
Redis client with automatic SLIM compression for JSON values.
Reduce your Redis memory usage by 40-50% without changing your code. SlimRedis is a drop-in wrapper for ioredis that automatically encodes JSON values using the SLIM protocol.
Why SlimRedis?
| Problem | Solution |
|---------|----------|
| Redis stores JSON as strings (inefficient) | SLIM compresses structured data by 40-50% |
| High Redis Cloud/memory costs | Same data, less storage |
| Large payloads = high latency | Smaller values = faster network transfer |
| Learning new APIs is tedious | Same ioredis API with Json suffix |
Quick Start
npm install @matteuccimarco/slim-redis ioredisimport { createSlimRedis } from '@matteuccimarco/slim-redis';
const redis = createSlimRedis('redis://localhost:6379');
// Store JSON with automatic SLIM compression
await redis.setJson('user:123', {
name: 'Alice',
preferences: { theme: 'dark', notifications: true },
roles: ['admin', 'user']
});
// Retrieve with automatic decoding
const user = await redis.getJson('user:123');
// => { name: 'Alice', preferences: { theme: 'dark', notifications: true }, roles: ['admin', 'user'] }
// Check your savings
console.log(redis.getStats().savingsPercent); // "~42%"Features
- 40-50% compression on typical JSON data
- Zero config - just add
Jsonsuffix to your methods - Full ioredis compatibility - access underlying client anytime
- Automatic fallback - reads legacy JSON data seamlessly
- Built-in statistics - track compression ratios in real-time
- TypeScript first - full type safety
API Reference
String Commands
// Set with optional TTL
await redis.setJson('key', { data: 'value' });
await redis.setJson('key', { data: 'value' }, 3600); // expires in 1 hour
await redis.setexJson('key', 3600, { data: 'value' }); // same as above
// Get
const value = await redis.getJson<MyType>('key');
// Batch operations
await redis.msetJson({
'user:1': { name: 'Alice' },
'user:2': { name: 'Bob' },
});
const users = await redis.mgetJson<User>(['user:1', 'user:2']);Hash Commands
// Set hash fields
await redis.hsetJson('user:123', 'profile', { name: 'Alice' });
await redis.hmsetJson('user:123', {
profile: { name: 'Alice' },
settings: { theme: 'dark' },
});
// Get hash fields
const profile = await redis.hgetJson('user:123', 'profile');
const all = await redis.hgetallJson('user:123');List Commands
// Push to lists
await redis.lpushJson('events', { type: 'click' }, { type: 'view' });
await redis.rpushJson('events', { type: 'submit' });
// Pop from lists
const first = await redis.lpopJson('events');
const last = await redis.rpopJson('events');
// Get range
const events = await redis.lrangeJson('events', 0, -1);Pub/Sub Commands
// Publish SLIM-encoded messages
await redis.publishJson('channel', { event: 'update', data: {...} });
// Subscribe with automatic decoding
redis.subscribeJson('channel', (message, channel) => {
console.log('Received:', message);
});Statistics
const stats = redis.getStats();
// {
// bytesBeforeEncoding: 10240,
// bytesAfterEncoding: 6144,
// operationCount: 100,
// errors: 0,
// compressionRatio: 0.6,
// savingsPercent: "40.0%"
// }
redis.resetStats(); // Reset countersUnderlying Client
// Access ioredis client for non-JSON operations
await redis.client.incr('counter');
await redis.client.expire('key', 3600);
await redis.client.del('key');
// Connection management
await redis.quit(); // Graceful close
redis.disconnect(); // Force closeConfiguration
import { SlimRedis } from '@matteuccimarco/slim-redis';
const redis = new SlimRedis('redis://localhost:6379', {
// Add prefix to all keys (default: '')
keyPrefix: 'myapp',
// Track compression stats (default: true)
trackStats: true,
// Fallback to JSON.parse for legacy data (default: true)
fallbackToJson: true,
});Compression Examples
| Data Type | JSON | SLIM | Savings | |-----------|------|------|---------| | User session | 500B | 300B | 40% | | Product list (10 items) | 2KB | 1.1KB | 45% | | Analytics event | 200B | 115B | 42% | | Cache entry (complex) | 5KB | 2.8KB | 44% |
Real-world impact:
- 100K sessions × 200B saved = ~20MB less RAM
- At $0.10/MB/month on Redis Cloud = $2/month saved per 100K sessions
Use Cases
Session Storage
const sessions = new SlimRedis('redis://...', { keyPrefix: 'sess' });
await sessions.setexJson('abc123', 86400, {
userId: 'user_001',
role: 'admin',
permissions: ['read', 'write', 'delete'],
preferences: { theme: 'dark', lang: 'en' },
});Caching Layer
async function getCached<T>(key: string, factory: () => Promise<T>): Promise<T> {
const cached = await redis.getJson<T>(key);
if (cached) return cached;
const fresh = await factory();
await redis.setexJson(key, 300, fresh);
return fresh;
}
const user = await getCached('user:123', () => db.users.findById(123));Real-time Events
// Publisher
await redis.publishJson('events', {
type: 'order_placed',
orderId: 'ord_123',
timestamp: Date.now(),
});
// Subscriber
redis.subscribeJson('events', (event) => {
if (event.type === 'order_placed') {
processOrder(event.orderId);
}
});Benchmarks
Run benchmarks locally:
npm run benchmarkTypical results (500 iterations, localhost Redis):
| Metric | JSON | SLIM | Difference | |--------|------|------|------------| | SET (small) | 45ms | 52ms | +15% | | GET (small) | 38ms | 44ms | +16% | | Storage | 156B | 89B | -43% | | SET (large) | 120ms | 145ms | +21% | | GET (large) | 95ms | 118ms | +24% | | Storage | 8.2KB | 4.5KB | -45% |
Trade-off: ~15-25% CPU overhead for 40-45% memory savings.
Compatibility
- Node.js: 18+
- ioredis: 5.x
- Redis: 5.x, 6.x, 7.x
- Redis Cluster: Supported
- TypeScript: 5.x
How It Works
SlimRedis uses the SLIM protocol to encode JSON:
JSON: {"users":[{"id":1,"name":"Mario","active":true},{"id":2,"name":"Luigi","active":false}]}
SLIM: {users:|2|id#,name$,active?|
1,Mario,T
2,Luigi,F}Key optimizations:
- Tabular format for arrays of objects (keys declared once)
- Type prefixes (
#number,?boolean) instead of syntax - Minimal delimiters (no quotes on keys/simple strings)
Related Projects
- slim-protocol-core - Core SLIM encoder/decoder
- slim-db - Embedded database with SLIM storage (coming soon)
Contributing
Contributions are welcome! Please read our contributing guidelines and submit PRs.
git clone https://github.com/matteuccimarco/slim-redis
cd slim-redis
npm install
npm testLicense
MIT - see LICENSE
Built with SLIM by Marco Matteuccci
