yq-store
Version:
A high-performance, persistent and in-memory key-value store with TTL support, built for Node.js applications.
941 lines (721 loc) β’ 28.8 kB
Markdown
# yq-store
> A blazingly fast, zero-dependency key-value store that just works. Built for developers who need reliable data persistence without the complexity.
[](https://www.npmjs.com/package/yq-store)
[](https://opensource.org/licenses/MIT)
[](http://www.typescriptlang.org/)
[](https://nodejs.org/)
## Table of Contents
- [π Why yq-store?](#-why-yq-store) - *Discover what makes yq-store special*
- [β‘ Quick Start](#-quick-start) - *Get up and running in 30 seconds*
- [β¨ Key Features](#-key-features) - *What you get out of the box*
- [ποΈ How It Works](#οΈ-how-it-works) - *The architecture that powers performance*
- [π¦ Installation](#-installation) - *Simple npm install*
- [π Usage Guide](#-usage-guide) - *Learn by example*
- [Basic Operations](#basic-operations) - *Store, retrieve, and delete data*
- [Time-To-Live (TTL)](#time-to-live-ttl) - *Automatic data expiration*
- [Event Monitoring](#event-monitoring) - *React to store changes*
- [Batch Operations](#batch-operations) - *Process multiple operations efficiently*
- [Transactions](#transactions) - *ACID-compliant data operations*
- [Querying & Filtering](#querying--filtering) - *Find data with ease*
- [Storage Modes](#storage-modes) - *Memory vs persistent storage*
- [File-Based Caching with YqCacher](#file-based-caching-with-yqcacher) - *High-performance file adapter*
- [π§ Configuration](#-configuration) - *Customize for your needs*
- [π API Reference](#-api-reference) - *Complete method documentation*
- [β‘ Performance](#-performance) - *Benchmarks and optimization tips*
- [π― Use Cases](#-use-cases) - *Real-world applications*
- [π Troubleshooting](#-troubleshooting) - *Common issues and solutions*
- [β FAQ](#-faq) - *Frequently asked questions*
- [π€ Contributing](#-contributing) - *Join the community*
- [π Support](#-support) - *Get help when you need it*
- [π License](#-license) - *MIT licensed*
## π Why yq-store?
Building applications shouldn't mean wrestling with complex databases or sacrificing performance for simplicity. **yq-store** gives you the best of both worlds:
- **Zero Setup Complexity**: No database servers, no configuration files, no headaches
- **Production Ready**: Built on proven foundations with enterprise-grade reliability
- **Developer Friendly**: TypeScript-first with intuitive APIs that feel natural
- **Performance Focused**: Optimized for real-world workloads, not just benchmarks
## β‘ Quick Start
Get started in less than a minute:
```typescript
import { YqStore } from 'yq-store';
// Create your store
const store = await YqStore.create();
// Store some data
await store.set('user:123', {
name: 'Sarah Chen',
email: 'sarah@example.com',
preferences: { theme: 'dark', notifications: true }
});
// Retrieve it later
const user = await store.get('user:123');
console.log(`Welcome back, ${user.name}!`);
// Clean up when done
await store.close();
```
That's it! Your data is automatically persisted to disk and will survive application restarts.
## β¨ Key Features
### ποΈ **Blazing Fast Performance**
- 20,000+ reads per second
- Optimized storage backend with concurrent access support
- Intelligent indexing and caching
### π‘οΈ **Rock Solid Reliability**
- ACID transactions
- Automatic data recovery
- Battle-tested foundation
### β° **Smart Data Management**
- Built-in TTL (Time-To-Live) support
- Automatic cleanup and compaction
- Configurable memory limits
### π― **Developer Experience**
- Full TypeScript support
- Zero external dependencies
- Intuitive, promise-based API
### π **Powerful Querying**
- Prefix and suffix filtering
- Pagination support
- Batch operations
## ποΈ How It Works
**yq-store** is built on a modern, performance-optimized architecture:
```
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Your App βββββΆβ yq-store βββββΆβ Storage Layer β
β β β β β β
β TypeScript API β β β’ Event System β β β’ Persistence β
β Promise-based β β β’ TTL Management β β β’ Transactions β
β Type-safe β β β’ Auto Cleanup β β β’ Indexing β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
```
**Key Architecture Benefits:**
- **Concurrent Access**: Multiple readers and writers supported
- **Automatic Optimization**: Background cleanup and performance tuning
- **Memory Efficiency**: Configurable limits prevent resource bloat
- **Event-Driven**: Real-time notifications for all store operations
## π¦ Installation
```bash
npm install yq-store
```
**Requirements:**
- Node.js 22.15+ or Bun 1.2+
- TypeScript 5.8+ (recommended)
**Platform Support:**
- β
Linux (x64, ARM64)
- β
macOS (Intel, Apple Silicon)
- β
Windows (x64)
No additional setup required! yq-store works out of the box with zero configuration.
## π Usage Guide
### Basic Operations
The core operations you'll use every day:
```typescript
import { YqStore } from 'yq-store';
// Create your store
const store = await YqStore.create();
// Store any JSON-serializable data
await store.set('product:laptop-123', {
name: 'MacBook Pro',
price: 3999,
specs: {
cpu: 'M3 Pro',
memory: '48GB',
storage: '1TB SSD'
},
inStock: true
});
// Retrieve with full type safety
interface Product {
name: string;
price: number;
specs: Record<string, string>;
inStock: boolean;
}
const laptop = await store.get<Product>('product:laptop-123');
if (laptop) {
console.log(`${laptop.name} - $${laptop.price}`);
console.log(`In stock: ${laptop.inStock ? 'Yes' : 'No'}`);
}
// Check existence without retrieving
const exists = await store.has('product:laptop-123');
console.log(`Product exists: ${exists}`);
// Remove when no longer needed
const wasDeleted = await store.delete('product:laptop-123');
console.log(`Deletion successful: ${wasDeleted}`);
// Get store statistics
const activeCount = await store.getSize('active');
const totalCount = await store.getSize('all');
console.log(`Active entries: ${activeCount}, Total: ${totalCount}`);
```
### Time-To-Live (TTL)
Perfect for sessions, caches, and temporary data:
```typescript
// Cache API responses for 5 minutes
await store.set('api:weather:london', {
temperature: 18,
condition: 'partly-cloudy',
humidity: 65,
timestamp: Date.now()
}, 300); // 300 seconds = 5 minutes
// Store user sessions that expire in 24 hours
await store.set('session:user-456', {
userId: '456',
loginTime: new Date().toISOString(),
permissions: ['read', 'write'],
csrfToken: 'abc123xyz'
}, 86400); // 24 hours
// The data automatically disappears when it expires
setTimeout(async () => {
const weather = await store.get('api:weather:london');
console.log(weather); // null - expired and cleaned up
}, 301000); // Check after expiration
```
### Event Monitoring
Stay informed about what's happening in your store:
```typescript
// Monitor store lifecycle
store.on('ready', () => {
console.log('π’ Store is ready for operations');
});
store.on('close', () => {
console.log('π΄ Store has been closed');
});
// Track data operations
store.on('set', (key, value) => {
console.log(`π Stored: ${key}`);
// Log to analytics, update UI, etc.
});
store.on('delete', (key) => {
console.log(`ποΈ Deleted: ${key}`);
});
store.on('expire', (key) => {
console.log(`β° Expired: ${key}`);
});
// Monitor performance and maintenance
store.on('compact:start', () => {
console.log('π§ Starting store optimization...');
});
store.on('compact:end', (stats) => {
console.log(`β
Optimization complete. Processed ${stats.keysProcessed} keys`);
});
// Handle errors gracefully
store.on('error', (error) => {
console.error('β Store error:', error.message);
// Send to error tracking service
});
```
### Batch Operations
Process multiple operations efficiently and atomically:
```typescript
// Import user data in a single atomic operation
await store.batch([
{
type: 'put',
key: 'user:alice',
value: { name: 'Alice Johnson', role: 'admin' }
},
{
type: 'put',
key: 'user:bob',
value: { name: 'Bob Smith', role: 'user' },
ttlSeconds: 3600 // Bob's account expires in 1 hour
},
{
type: 'put',
key: 'user:charlie',
value: { name: 'Charlie Brown', role: 'moderator' }
},
{
type: 'del',
key: 'user:old-account' // Remove old account
}
]);
console.log('β
All users imported successfully!');
```
### Transactions
Ensure data consistency with ACID transactions:
```typescript
// Transfer credits between user accounts
const tx = store.createTransaction();
try {
// Get current balances
const sender = await store.get<{credits: number}>('user:alice:credits');
const receiver = await store.get<{credits: number}>('user:bob:credits');
if (!sender || sender.credits < 100) {
throw new Error('Insufficient credits');
}
// Prepare the transfer
tx.put('user:alice:credits', { credits: sender.credits - 100 });
tx.put('user:bob:credits', { credits: (receiver?.credits || 0) + 100 });
tx.put('transaction:log', {
from: 'alice',
to: 'bob',
amount: 100,
timestamp: Date.now()
});
// Execute atomically
await tx.commit();
console.log('π° Transfer completed successfully!');
} catch (error) {
// Rollback on any error
tx.rollback();
console.error('β Transfer failed:', error.message);
}
```
### Querying & Filtering
Find and process data efficiently:
```typescript
// Find all user records
const userKeys = await store.listKeys({ prefix: 'user:' });
console.log(`Found ${userKeys.length} users`);
// Get paginated results
const firstPage = await store.list<User>({
prefix: 'user:',
limit: 10,
page: 1
});
firstPage.forEach(({ key, value }) => {
console.log(`${key}: ${value.name} (${value.role})`);
});
// Process all session data
await store.forEach<Session>((key, session) => {
if (session.lastActivity < Date.now() - 86400000) {
console.log(`Inactive session: ${key}`);
// Could mark for cleanup
}
}, {
prefix: 'session:',
limit: 1000 // Process in batches
});
// Find configuration files
const configKeys = await store.listKeys({ suffix: '.config' });
configKeys.forEach(key => {
console.log(`Config file: ${key}`);
});
```
### Storage Modes
Choose the right storage mode for your use case:
```typescript
// In-memory store (perfect for testing or temporary data)
const memoryStore = await YqStore.create({
storage: {
type: 'memory',
maxEntries: 50000,
maxMemory: 100 * 1024 * 1024 // 100MB limit
}
});
// Persistent store with custom location
const persistentStore = await YqStore.create({
storage: {
type: 'persistence',
persistence: {
dbDir: './data/stores',
dbFileName: 'my-application-store'
}
},
compactionInterval: 1800000, // Compact every 30 minutes
softDelete: true // Enable soft deletes for data recovery
});
```
### File-Based Caching with YqCacher
For applications that need high-performance file-based caching with automatic cleanup and namespace support, **YqCacher** provides a specialized file adapter:
```typescript
import { YqCacher } from 'yq-store/file-adapter';
// Create and initialize a file-based cache
const cache = await YqCacher.create({
cacheDir: './cache',
ttl: 3600, // 1 hour default TTL
evictionInterval: 300000, // Clean expired files every 5 minutes
maxItems: 10000 // Maximum items before LRU eviction
});
// Store data with automatic file management
await cache.set('user:profile:123', {
name: 'John Doe',
email: 'john@example.com',
lastLogin: new Date().toISOString()
}, 7200); // 2 hours TTL
// Use namespaces for organized storage
await cache.set('api:weather', weatherData, 300, 'london');
await cache.set('api:weather', weatherData, 300, 'paris');
// Retrieve with type safety and namespace support
const profile = await cache.get<UserProfile>('user:profile:123');
const londonWeather = await cache.get('api:weather', 'london');
// Method overloading: access data with or without namespaces
const globalData = await cache.get('shared:config'); // Global scope
const namespacedData = await cache.get('shared:config', 'production'); // Namespaced scope
// Check existence with namespace overloading
const existsGlobal = await cache.has('user:profile:123'); // Global scope
const existsNamespaced = await cache.has('user:profile:123', 'tenant-a'); // Namespaced scope
// Delete operations support namespace overloading
await cache.delete('temp:data'); // Delete from global scope
await cache.delete('temp:data', 'session-123'); // Delete from specific namespace
const stats = await cache.getStats();
console.log(`Cache: ${stats.totalEntries} entries, Hot cache: ${stats.hotCache.size}/${stats.hotCache.maxSize}`);
// Clean up when done
await cache.close();
```
#### YqCacher Features
- **ποΈ Namespace Support**: Organize cache files into logical groups with complete data isolation
- **π Method Overloading**: Access data with or without namespaces using the same intuitive API
- **β‘ Blazing Fast**: Highly optimized for maximum throughput
- **π₯ Hot Cache**: In-memory cache for frequently accessed entries (configurable size)
- **π§Ή Automatic Cleanup**: Expired files are automatically removed
- **π Rich Statistics**: Track entry counts, hot cache stats, and access patterns
- **π Data Integrity**: Atomic operations prevent corruption
- **π― Type Safety**: Full TypeScript support with generics and method overloads
- **π Non-Blocking**: Doesn't prevent process exit by default
#### YqCacher Configuration
```typescript
const cache = await YqCacher.create({
// Storage location
cacheDir: './cache',
// TTL settings
ttl: 3600, // Default expiration in seconds
// Maintenance
evictionInterval: 300000, // Cleanup frequency in milliseconds
maxItems: 1000000, // Maximum items before LRU eviction
// Performance tuning
hotCacheSize: 1000, // In-memory cache size (0 to disable)
eviction: true, // Enable LRU eviction
// Process behavior
keepAlive: false, // Don't block process exit (default)
// Security
encryptNamespace: false, // Encrypt namespace directory names
// File organization
softDelete: true, // Enable soft delete mode
});
```
#### YqCacher Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `cacheDir` | `string` | `'./cache'` | Directory for cache files and metadata |
| `ttl` | `number` | `0` | Default TTL in seconds (0 = no expiration) |
| `maxItems` | `number` | `1000000` | Maximum items before LRU eviction |
| `hotCacheSize` | `number` | `1000` | In-memory LRU cache size (0 to disable) |
| `eviction` | `boolean` | `false` | Enable automatic LRU eviction |
| `evictionInterval` | `number` | `60000` | Eviction check interval in ms |
| `keepAlive` | `boolean` | `false` | Keep process alive while cache is open |
| `softDelete` | `boolean` | `true` | Mark deleted instead of removing |
| `encryptNamespace` | `boolean` | `false` | Hash namespace directory names |
| `debug` | `boolean` | `false` | Enable debug logging |
#### YqCacher Performance
YqCacher is optimized for extreme performance:
**Expected throughput (operations per second):**
| Operation | Cold (disk) | Hot (in-memory) | Scale |
|-----------|-------------|-----------------|-------|
| `get()` | 20-50K | 200K-1M | 10K-1M keys |
| `set()` | 10-30K | 10-30K | 10K-1M keys |
| `has()` | 50-100K | 1M+ | 10K-1M keys |
| `batch()` | 50-100K | 50-100K | 100 ops/batch |
**Scaling recommendations:**
| Total Keys | Hot Cache Size | Memory Usage |
|------------|----------------|--------------|
| 10K | `1000` | ~2-4MB |
| 100K | `5000` | ~20-40MB |
| 1M | `10000` | ~200-400MB |
#### When to Use YqCacher
**Choose YqCacher when you need:**
- File-based caching for better disk space management
- Namespace organization for complex applications
- High-performance caching without database overhead
- Automatic cleanup of expired cache files
- Direct file access for external tools
**Choose YqStore when you need:**
- Complex querying and filtering capabilities
- ACID transactions and data consistency
- Event monitoring and real-time updates
- Advanced indexing and search features
## π§ Configuration
Customize yq-store to fit your specific needs:
```typescript
const store = await YqStore.create({
// Automatic maintenance
compactionInterval: 3600000, // Compact every hour (0 = disabled)
ttl: 0, // Default TTL in seconds (0 = no expiration)
softDelete: true, // Enable soft deletes for data recovery
// Storage configuration
storage: {
type: 'persistence', // 'memory' or 'persistence'
maxEntries: 1000000, // Maximum number of entries
maxMemory: 500 * 1024 * 1024, // 500MB memory limit
persistence: {
dbDir: './data', // Where to store the database
dbFileName: 'app-store', // Custom database name
},
// LRU eviction settings
eviction: true, // Enable automatic eviction
evictionInterval: 60000, // Check every minute
}
});
```
### Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `compactionInterval` | `number` | `3600000` | Auto-compaction interval in milliseconds (0 = disabled) |
| `ttl` | `number` | `0` | Default TTL for entries in seconds (0 = no expiration) |
| `softDelete` | `boolean` | `true` | Enable soft delete mode for data recovery |
| `storage.type` | `'memory' \| 'persistence'` | `'persistence'` | Storage mode |
| `storage.maxEntries` | `number` | `1000000` | Maximum number of entries before eviction |
| `storage.maxMemory` | `number` | `undefined` | Memory limit in bytes |
| `storage.persistence.dbDir` | `string` | `os.tmpdir()` | Directory for database files |
| `storage.persistence.dbFileName` | `string` | auto-generated | Custom database filename |
## π API Reference
### Core Methods
#### `YqStore.create(options?: KvStoreOptions): Promise<YqStore>`
Creates and initializes a new store instance.
#### `has(key: string): Promise<boolean>`
Checks if a key exists and hasn't expired.
#### `get<T>(key: string): Promise<T | null>`
Retrieves a value by key with full type safety.
#### `set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>`
Stores a value with optional TTL expiration.
#### `delete(key: string): Promise<boolean>`
Deletes a key and returns whether it existed.
#### `getSize(): Promise<number>`
Gets the total count of active entries in the store.
#### `getSize(type: 'active' | 'deleted' | 'expired' | 'all'): Promise<number>`
Gets the count of entries by type.
#### `getSize(options: {prefix: string} | {suffix: string}): Promise<number>`
Gets the count of entries matching the filter.
### Query Methods
#### `listKeys(): Promise<string[]>`
Lists all keys in the store.
#### `listKeys(options: {prefix?: string, suffix?: string}): Promise<string[]>`
Lists keys matching the specified filters.
#### `list<T>(options?: ListOptions): Promise<Array<{key: string, value: T}>>`
Retrieves key-value pairs with pagination support.
```typescript
interface ListOptions {
prefix?: string;
suffix?: string;
limit?: number;
page?: number;
}
```
#### `forEach<T>(callback: (key: string, value: T) => void, options?: ForEachOptions): Promise<void>`
Iterates over key-value pairs matching criteria.
```typescript
interface ForEachOptions {
prefix?: string;
suffix?: string;
limit?: number;
}
```
### Batch Operations
#### `batch(operations: BatchOperation[]): Promise<void>`
Executes multiple operations atomically.
```typescript
interface BatchOperation {
type: 'put' | 'del';
key: string;
value?: any;
ttlSeconds?: number;
}
```
#### `createTransaction(): Transaction`
Creates a new transaction for ACID operations.
```typescript
interface Transaction {
put<T>(key: string, value: T, ttlSeconds?: number): void;
del(key: string): void;
commit(): Promise<void>;
rollback(): void;
}
```
### Maintenance
#### `compact(): Promise<void>`
Manually triggers store compaction and optimization.
#### `clearSoftDeletedEntries(): Promise<number>`
Permanently removes soft-deleted entries.
#### `clearExpiredEntries(): Promise<number>`
Removes expired entries and returns count.
#### `close(): Promise<void>`
Closes the store and releases all resources.
### Events
#### `on<E>(event: E, listener: KvStoreEvents[E]): this`
Registers an event listener.
#### `off<E>(event: E, listener: KvStoreEvents[E]): this`
Removes an event listener.
### Available Events
- `ready` - Store is initialized and ready
- `db:ready` - Database connection established
- `set` - Key-value pair was stored
- `delete` - Key was deleted
- `expire` - Key expired due to TTL
- `evict` - Entries evicted due to memory limits
- `compact:start` - Compaction started
- `compact:end` - Compaction completed
- `error` - Error occurred
- `close` - Store was closed
## β‘ Performance
**yq-store** is optimized for real-world performance:
### Benchmark Results
*Tested on MacBook Pro M3 with 48GB RAM*
| Operation | Throughput | Notes |
|-----------|------------|-------|
| Sequential Writes | ~4,400 ops/sec | Single key operations |
| Batch Writes | ~8,600 ops/sec | 100 operations per batch |
| Sequential Reads | ~30,000 ops/sec | Cache-friendly access |
| Random Reads | ~32,000 ops/sec | Real-world mixed access |
### Performance Tips
1. **Use Batch Operations**: Group multiple writes for better throughput
2. **Configure Memory Limits**: Set appropriate `maxMemory` for your use case
3. **Choose Storage Mode**: Use memory mode for temporary data
4. **Monitor Events**: Track performance with timing events
5. **Tune Compaction**: Adjust interval based on write patterns
### Memory Usage
- **Base overhead**: ~2-5MB for the store instance
- **Per entry**: ~100-200 bytes depending on key/value size
- **Configurable limits**: Set `maxMemory` to prevent unbounded growth
- **Automatic cleanup**: LRU eviction prevents memory bloat
## π― Use Cases
**yq-store** excels in these scenarios:
### π **Web Applications**
```typescript
// Session management
await store.set(`session:${sessionId}`, userSession, 3600);
// Feature flags
await store.set('feature:new-ui', { enabled: true, rollout: 0.1 });
// User preferences
await store.set(`prefs:${userId}`, { theme: 'dark', lang: 'en' });
```
### π **Microservices**
```typescript
// Service configuration
await store.set('config:api-keys', { stripe: 'sk_...', sendgrid: 'SG...' });
// Circuit breaker state
await store.set('circuit:payment-service', { state: 'closed', failures: 0 });
// Rate limiting
await store.set(`rate:${clientId}`, { requests: 1, window: Date.now() }, 60);
```
### π± **Desktop Applications**
```typescript
// Application state
await store.set('app:window-state', { x: 100, y: 100, width: 800, height: 600 });
// User data
await store.set('user:recent-files', ['/path/to/file1.txt', '/path/to/file2.txt']);
// Plugin configuration
await store.set('plugins:enabled', ['spell-check', 'auto-save', 'git-integration']);
```
### π§ͺ **Development & Testing**
```typescript
// Test fixtures
const testStore = await YqStore.create({ storage: { type: 'memory' } });
await testStore.set('test:user', mockUser);
// Development cache
await store.set('dev:api-response', cachedResponse, 300);
```
## π Troubleshooting
### Common Issues
#### Store fails to initialize
```typescript
// β Problem
const store = new YqStore(); // Don't use constructor directly
// β
Solution
const store = await YqStore.create(); // Always use create() method
```
#### Memory usage growing unbounded
```typescript
// β
Solution: Set memory limits
const store = await YqStore.create({
storage: {
maxEntries: 100000,
maxMemory: 100 * 1024 * 1024, // 100MB limit
eviction: true
}
});
```
#### Poor write performance
```typescript
// β Problem: Individual operations
for (const item of items) {
await store.set(item.key, item.value);
}
// β
Solution: Use batch operations
const operations = items.map(item => ({
type: 'put' as const,
key: item.key,
value: item.value
}));
await store.batch(operations);
```
#### Database locks or corruption
```typescript
// β
Solution: Always close the store properly
process.on('SIGINT', async () => {
await store.close();
process.exit(0);
});
```
### Error Handling
```typescript
// Proper error handling
store.on('error', (error) => {
console.error('Store error:', error);
// Implement your error recovery strategy
});
try {
await store.set('key', 'value');
} catch (error) {
console.error('Failed to set value:', error);
}
```
### Performance Issues
- **Slow reads**: Increase memory limits or use memory storage mode
- **Slow writes**: Use batch operations for bulk inserts
- **High memory usage**: Enable LRU eviction and set appropriate limits
- **Storage growing**: Adjust compaction interval or manually trigger compaction
## β FAQ
### General Questions
**Q: Is yq-store production ready?**
A: Yes, yq-store is built on battle-tested foundations and includes comprehensive error handling, transactions, and recovery mechanisms.
**Q: Can I use yq-store in serverless environments?**
A: Yes, yq-store works well in serverless environments. Use memory storage mode for better cold start performance.
**Q: Does yq-store support clustering or replication?**
A: yq-store is designed as a single-instance embedded database. For distributed scenarios, consider using it as a local cache with external synchronization.
### Technical Questions
**Q: What happens if my application crashes?**
A: All committed data is safely persisted to disk. Soft-deleted entries are preserved for recovery.
**Q: Can I access the data from multiple processes?**
A: No, yq-store is designed for single-process access. Multiple instances pointing to the same database file will cause conflicts.
**Q: How do I migrate data between versions?**
A: yq-store handles schema migrations automatically. For major version upgrades, consult the migration guide.
**Q: Is there a size limit for values?**
A: No hard limit, but performance is optimized for values under 1MB. For larger data, consider using YqCacher.
### Performance Questions
**Q: How does yq-store compare to Redis?**
A: yq-store offers simpler deployment (no server required) with comparable performance for single-instance scenarios.
**Q: Can I tune performance for my specific use case?**
A: Yes, adjust `maxMemory`, `compactionInterval`, and storage mode based on your read/write patterns.
## π€ Contributing
We love contributions! Here's how you can help:
1. **π Report Bugs**: [Open an issue](https://github.com/yuniqsolutions/yq-store/issues) with reproduction steps
2. **π‘ Suggest Features**: Share your ideas for improvements
3. **π Improve Docs**: Help make our documentation even better
4. **π§ Submit PRs**: Fix bugs or add features
### Development Setup
```bash
# Clone the repository
git clone https://github.com/yuniqsolutions/yq-store.git
cd yq-store
# Install dependencies
npm install
# Run tests
npm test
# Build the project
npm run build
```
### Contributing Guidelines
- Follow TypeScript best practices
- Add tests for new features
- Update documentation for API changes
- Use conventional commit messages
## π Support
Need help? We're here for you:
- **π Documentation**: You're reading it! Check the [API Reference](#-api-reference)
- **π Bug Reports**: [GitHub Issues](https://github.com/yuniqsolutions/yq-store/issues)
- **π¬ Discussions**: [GitHub Discussions](https://github.com/yuniqsolutions/yq-store/discussions)
- **π§ Email**: support@yuniqsolutions.tech
### Enterprise Support
Looking for enterprise features or professional support? Contact us at enterprise@yuniqsolutions.tech
## π License
MIT License - see the [LICENSE](LICENSE) file for details.
---
**Built with β€οΈ by Yuniq Solutions Tech**
*Star us on [GitHub](https://github.com/yuniqsolutions/yq-store) if yq-store helps you build amazing applications!*