Atomic Operations
Perform atomic operations on numeric values and manage key expiration. Use increment for counters and expire for TTL management.
Overview
Atomic operations are fundamental for building reliable distributed systems. The Store adapter provides atomic operations that are guaranteed to execute without interference from concurrent operations, making them perfect for counters, rate limiting, and expiration management. These operations ensure data consistency across multiple processes without requiring locks or complex synchronization mechanisms.
In distributed systems, multiple processes might modify the same key simultaneously. Atomic operations eliminate race conditions by guaranteeing that operations complete entirely or not at all. This makes them essential for building reliable, scalable applications that handle concurrent access correctly.
Atomic operations are essential in distributed systems where multiple processes might modify the same key simultaneously. They ensure data consistency without locks.
Increment Operation
The increment() method atomically increments a numeric value stored at a key. If the key doesn't exist, it's initialized to 0 before incrementing. This atomic behavior ensures that even when multiple processes increment the same counter simultaneously, each increment is counted correctly without race conditions.
Atomic increments are perfect for building counters, tracking usage, and implementing rate limiting. They eliminate the need for locks or complex synchronization, making your code simpler and more reliable. Understanding how to use increments effectively helps you build robust distributed systems.
Basic Usage
The increment() method is simple to use—just provide a key and it returns the new value after incrementing. If the key doesn't exist, it's automatically initialized to 0 before incrementing, so the first call returns 1.
handler: async ({ context }) => {
// Increment a counter
const newValue = await igniter.store.increment('page:views');
// If key didn't exist, newValue will be 1
// If key existed with value 5, newValue will be 6
return response.success({ views: newValue });
}Counter Patterns
Understanding common counter patterns helps you use atomic increments effectively in real-world scenarios. These patterns demonstrate how to track page views, monitor user activity, and implement distributed counters that work correctly across multiple instances of your application.
Expire Operation
The expire() method sets or updates the time-to-live (TTL) of a key. This is useful for managing cache expiration and cleaning up temporary data. Expiration ensures that data doesn't persist indefinitely, helping you manage memory and keep data fresh.
Understanding expiration patterns helps you implement automatic cleanup, session management, and temporary data storage. The expire() operation works independently of the set() operation, allowing you to update expiration times without modifying cached values.
Basic Usage
Set TTL on existing keys or update expiration times independently. This flexibility makes it easy to manage data lifecycle without recreating cached values.
handler: async ({ context }) => {
// Set TTL on an existing key
await igniter.store.set('user:123', userData);
await igniter.store.expire('user:123', 3600); // Expires in 1 hour
// Update expiration
await igniter.store.expire('user:123', 7200); // Extend to 2 hours
return response.success({ message: 'TTL set' });
}Expiration Patterns
Common expiration patterns help you manage data lifecycle effectively. These patterns demonstrate how to implement auto-expiring sessions, temporary data cleanup, and expiration refresh on access. Understanding these patterns helps you build robust data management systems.
Combined Operations
Combining atomic operations enables powerful patterns like rate limiting, distributed locks, and request counting. These patterns combine increments and expiration to solve complex distributed systems problems reliably. Understanding how to combine operations effectively helps you build robust, scalable applications.
Atomic operations work together seamlessly—you can increment counters and set expiration atomically, ensuring consistent behavior even under high concurrency. These combined operations eliminate race conditions and make distributed systems programming straightforward.
Best Practices
Following best practices ensures your atomic operations work correctly and efficiently. These practices cover counter initialization, expiration management, TTL values, and race condition prevention. Applying these practices helps you build reliable distributed systems.
Best practices prevent common mistakes like manual counter initialization, forgotten expiration settings, and inappropriate TTL values. They ensure your atomic operations work correctly even under high concurrency and help you build robust distributed systems.
Error Handling
Atomic operations can fail due to network issues, Redis unavailability, or other transient errors. Handle errors gracefully to ensure your application continues functioning even when atomic operations fail. Good error handling prevents atomic operation failures from breaking your application.
Error handling for atomic operations requires balancing reliability with performance. Always have fallback strategies that allow your application to continue functioning when atomic operations fail temporarily.
Handle errors gracefully:
const safeIncrement = async (
key: string,
context: AppContext
): Promise<number | null> => {
try {
return await igniter.store.increment(key);
} catch (error) {
context.logger.error('Failed to increment counter', { error, key });
return null;
}
};
const safeExpire = async (
key: string,
ttl: number,
context: AppContext
): Promise<boolean> => {
try {
await igniter.store.expire(key, ttl);
return true;
} catch (error) {
context.logger.error('Failed to set expiration', { error, key, ttl });
return false;
}
};Performance Considerations
Optimizing atomic operation performance involves understanding when to batch operations, how to monitor operations, and how to minimize Redis round trips. These considerations help you build high-performance applications that use atomic operations efficiently.
Performance optimization for atomic operations ensures your application scales well and remains responsive under load. Understanding these considerations helps you build efficient distributed systems.
Real-World Examples
These real-world examples demonstrate practical atomic operation patterns you can use in production applications. They show how to track API usage, implement feature flags with usage limits, and build production-ready systems using atomic operations.
Real-world examples help you understand how atomic operations fit into actual applications. These patterns address common scenarios and provide production-ready solutions you can adapt for your own use cases.
Pub/Sub Messaging
Publish and subscribe to channels for event-driven communication. Build real-time features, microservices communication, and decoupled architectures using Pub/Sub.
Advanced Usage
Advanced patterns and techniques for using the Store adapter. Learn about error handling, performance optimization, monitoring, and production best practices.