For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

OpenAlgo in-memory caches: BrokerSymbolCache, auth, feed token, broker and order mode caches, API key caches, backed by symtoken, auth and api_keys tables in db/openalgo.db

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:

verify_api_key flow: sha256 cache key, invalid cache, verified cache, then Argon2 verification against api_keys with results cached and invalid attempts tracked

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

Cache
TTL
Purpose

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

Component
Size
Memory

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

Operation
Complexity
Latency

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

  1. TTL Expiry - Caches auto-expire based on TTL

  2. Session Expiry - Symbol and auth caches reset at 3:00 AM IST

  3. 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

File
Purpose

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

  1. Always check cache first - Use cache methods before DB queries

  2. Invalidate on mutation - Clear relevant cache entries on data changes

  3. Monitor hit rates - Investigate if hit rate drops below 90%

  4. Respect TTLs - Don't manually extend cache entries

  5. Handle cache misses gracefully - Fall back to DB on miss

Last updated

Was this helpful?