04 - Cache Architecture
Overview
OpenAlgo implements a multi-layer caching system to achieve high performance with 100,000+ trading symbols. The caching architecture minimizes database queries, reduces latency, and ensures fast API responses during high-frequency trading operations.
Cache Architecture Diagram

Cache Types
1. Symbol Cache (BrokerSymbolCache)
High-performance in-memory cache for 100,000+ trading symbols.
Location: database/token_db_enhanced.py
Features:
O(1) lookups via multiple indexes
~50MB memory for 100K symbols
Session-based TTL (resets at 3:00 AM IST)
Cache statistics tracking
underlyings_by_exchange holds only underlyings that have at least one CE or PE row, which is what the option chain, IV chart and GEX dropdowns need. tradable_underlyings_by_exchange is the union of those with underlyings that have at least one unexpired FUT row, so futures-only MCX commodities such as NATURALGASMINI still appear in the generic symbol search.
Cache Population:
Lookup Example:
2. Authentication Caches
Location: database/auth_db.py
Session-Based TTL Calculation:
3. API Key Caches
Three-Level API Key Verification:

Implementation:
A cache miss walks every row in api_keys and calls ph.verify() on each, so the invalid cache is what keeps a key-guessing loop from turning into repeated Argon2 work. Failed attempts are also recorded through InvalidAPIKeyTracker in database/traffic_db.py, which is what feeds the API-key ban threshold in the security dashboard.
Cache Lifecycle
1. Startup Restoration
On application startup, caches are restored from database:
2. Login Population
After successful broker authentication:
Cache Hook:
3. Logout Cleanup
On logout, caches are cleared:
Cache Statistics & Health
Statistics Tracking
Health Monitoring
Cache Configuration
Environment Variables
TTL Summary
auth_cache
Until session expiry
Auth token storage
feed_token_cache
Until session expiry
WebSocket feed tokens
broker_cache
50 minutes
Broker name lookups
verified_api_key_cache
10 hours
Valid API key user IDs
invalid_api_key_cache
5 minutes
Failed API key attempts
order_mode_cache
60 seconds
Auto versus semi-auto order mode per key (maxsize 128)
symbol_cache
Until session expiry
Trading symbols
The symbol cache is not a TTLCache. BrokerSymbolCache.is_cache_valid() compares the current IST time against a next_reset_time derived from SESSION_EXPIRY_TIME, so it expires on a daily boundary rather than on a rolling window.
Performance Characteristics
Memory Usage
Symbol Cache (100K symbols)
~500 bytes/symbol
~50 MB
Auth Cache (1024 entries)
~1 KB/entry
~1 MB
API Key Cache (1024 entries)
~100 bytes/entry
~100 KB
Total
~52 MB
Lookup Performance
Symbol lookup (cached)
O(1)
<1 ms
Auth token lookup (cached)
O(1)
<1 ms
API key verification (cached)
O(1)
<1 ms
API key verification (DB)
O(1) + Argon2
~100 ms
Symbol lookup (DB fallback)
O(log n)
~5 ms
Cache Invalidation
Automatic Invalidation
TTL Expiry - Caches auto-expire based on TTL
Session Expiry - Symbol and auth caches reset at 3:00 AM IST
Logout - All user-specific caches cleared
Manual Invalidation
Cross-Process Invalidation
The WebSocket proxy can run in a separate process, so clearing a dict in the Flask worker does not reach it. database/cache_invalidation.py publishes on the shared ZeroMQ publisher that broker adapters already use. CacheInvalidationPublisher.publish_invalidation(user_id, cache_type) sends topic CACHE_INVALIDATE_{cache_type}_{user_id} where cache_type is AUTH, FEED or ALL; the convenience wrappers are publish_auth_cache_invalidation, publish_feed_cache_invalidation and publish_all_cache_invalidation. The proxy's SUB listener consumes the message and clears its own copy.
Key Files Reference
database/token_db_enhanced.py
Symbol cache implementation
database/auth_db.py
Auth and API key caches
database/cache_restoration.py
Startup cache restoration
database/master_contract_cache_hook.py
Cache lifecycle hooks
Best Practices
Always check cache first - Use cache methods before DB queries
Invalidate on mutation - Clear relevant cache entries on data changes
Monitor hit rates - Investigate if hit rate drops below 90%
Respect TTLs - Don't manually extend cache entries
Handle cache misses gracefully - Fall back to DB on miss
Last updated
Was this helpful?