Skip to main content

Multi-Tier Caching

Quint uses a two-tier caching system to avoid re-scoring identical events. Events are hashed by their essential fields (action, target, data fields, agent type) to produce a signature. If the same signature has been scored before, the cached result is returned instantly.

Architecture

Event arrives → Compute signature hash

              ┌─────┴──────┐
              │  L1: Redis  │ ← TTL: 24 hours
              └─────┬──────┘
                    │ miss
              ┌─────┴──────────┐
              │  L2: PostgreSQL │ ← TTL: 7 days
              └─────┬──────────┘
                    │ miss
              ┌─────┴──────┐
              │  Score event │ → Write back to L1 + L2
              └─────────────┘

Signature Hashing

The cache signature is computed from event essentials — fields that determine the score outcome:
signature_fields = {
    "action": event.action,
    "agent_type": event.agent.agent_type,
    "target_resource_type": event.target.resource_type,
    "sensitivity_level": event.target.sensitivity_level,
    "data_fields": sorted(event.data_fields_accessed),
    "mcp_verified": event.mcp_context.is_verified
}

signature_hash = sha256(json.dumps(signature_fields, sort_keys=True))
Fields NOT included in the signature (they don’t change the score):
  • event_id (unique per event)
  • timestamp (temporal modifier uses baseline, not absolute time)
  • session_id (session context is separate)

Cache Tiers

L1: Redis

SettingDefaultDescription
TTL86,400 seconds (24h)How long cached scores persist
Max per customer10,000Maximum cached events per customer
Eviction: LRU within the per-customer limit. When a customer exceeds 10,000 cached events, the least recently used entries are evicted.

L2: PostgreSQL

SettingDefaultDescription
TTL7 daysHow long cached scores persist
Uses the event_cache table with a unique constraint on (customer_id, signature_hash).

Cache Manager API

from src.cache.manager import CacheManager

manager = CacheManager(redis_client, db_session)

# Check cache before scoring
cached = await manager.get(customer_id, signature_hash)
if cached:
    return cached  # Cache hit — skip scoring entirely

# After scoring, write to cache
await manager.set(customer_id, signature_hash, score_response)

Cache Hit Rate

The cache_hit field in score responses indicates whether a cached result was used:
{
  "event_id": "evt-003",
  "score": 12,
  "risk_level": "low",
  "cache_hit": true,
  "scoring_source": "graph_reasoner"
}
Typical cache hit rates vary by customer:
  • High repetition workloads (CI/CD bots, monitoring agents): 60-80% hit rate
  • Diverse workloads (user-facing agents, varied tasks): 20-40% hit rate