Per-Request Query Caching
CQL includes a powerful per-request query caching system that automatically caches SQL query results during a single request. This eliminates duplicate database queries within the same request while ensuring cache isolation between requests.
Key Features
Automatic SQL deduplication: The same SQL query with identical parameters will hit the cache instead of the database if executed again during the same request
Per-request lifecycle: Cache is automatically cleared at the start of each new request
Thread-safe: Safe to use in multi-threaded applications
Zero configuration: Just add middleware to your web framework
Memory efficient: Configurable cache size with automatic eviction
Framework agnostic: Works with all popular Crystal web frameworks
How It Works
The caching system works at the SQL level by:
Generating a unique cache key from the SQL query and parameters
Checking the cache before executing any database query
Storing results in memory after the first execution
Returning cached results for subsequent identical queries
Clearing the cache at the end of each request
Quick Start
1. Enable in Web Framework
Kemal
Lucky
Amber
Azu
Generic HTTP::Server
2. Manual Integration
For custom frameworks or manual control:
Example Usage
Advanced Usage
Block-Based Request Scoping
Enable/Disable Caching
Cache Statistics and Monitoring
What Gets Cached
The caching system works with all CQL query methods:
User.all- SELECT queriesUser.find(1)- Single record lookupsUser.where(active: true).count- Aggregate queriesUser.where(name: "John").first- Limited queriesComplex joins and subqueries
Custom SQL via
Query#get,Query#all, etc.
Cache Key Generation
Cache keys are generated using:
The complete SQL query string
All query parameters
MD5 hash for consistent, short keys
This ensures that only truly identical queries hit the cache.
Performance Benefits
Typical performance improvements:
2-10x faster for repeated queries
Reduced database load during high traffic
Lower query latency for complex reports
Better scalability with caching layers
Best Practices
1. Use with Read-Heavy Operations
Per-request caching works best for:
Dashboard queries that aggregate data
Navigation menus loaded multiple times
User permissions checked repeatedly
Lookup tables accessed frequently
2. Monitor Cache Statistics
3. Configure Cache Size
Limitations
Per-request only: Cache doesn't persist across requests
Memory storage: Cache is stored in application memory
Read queries only: Only SELECT queries benefit from caching
Identical SQL required: Slight variations in SQL won't hit cache
Thread Safety
The caching system is fully thread-safe and can be used in:
Multi-threaded web servers
Concurrent request handling
Background job processing
Fiber-based concurrency
Troubleshooting
Cache Not Working
Check if enabled:
CQL::Cache::RequestQueryCacheHelper.enabled?Verify middleware setup: Ensure before/after hooks are called
Check SQL consistency: Use cache stats to see hit/miss ratios
Monitor memory usage: Large result sets might impact performance
Debugging Cache Behavior
Azu Framework Integration
The Azu framework is a Crystal application development toolkit with expressive, elegant syntax. CQL's per-request query caching integrates seamlessly with Azu through multiple approaches:
Handler-Based Integration
Controller-Based Integration
Manual Hook Integration
Integration Examples
See the complete working examples for different frameworks:
examples/per_request_query_cache_demo.cr- General usage patternsexamples/azu_query_cache_demo.cr- Azu-specific integration examples
These examples demonstrate:
Basic usage patterns
Web framework integration
Performance comparisons
Statistics monitoring
Error handling
Real-world application patterns
The per-request query caching system provides significant performance benefits with minimal setup, making it an excellent addition to any CQL-based application, especially those built with the Azu framework.
Last updated
Was this helpful?