Production-grade caching with zero configuration. 0.5-2ms responses, up to 99.9% cache hit rates in stable production workloads, tenant-aware security built-in.
FraiseQL's Automatic Persisted Queries (APQ) system provides production-ready query caching with built-in multi-tenant security. Unlike traditional APQ implementations, FraiseQL ensures tenant isolation at the cache layer, preventing cross-tenant data leakage while delivering sub-millisecond response times.
| Metric | Without APQ | With APQ | Improvement |
|---|---|---|---|
| Response Time | 15-50ms | ✅ 0.5-2ms | ✅ 10-25x faster |
| Cache Hit Rate | N/A | ✅ Up to 99.9% | ✅ Stable workloads |
| Bandwidth Usage | 100% | ✅ 30% | ✅ 70% reduction |
| External Dependencies | Redis/Memcached | ✅ None (PostgreSQL) | ✅ Simplified stack |
from fraiseql.fastapi import create_app
from fraiseql.storage.backends import PostgreSQLBackend
# APQ automatically enabled with PostgreSQL backend
app = create_app(
database_url="postgresql://localhost/db",
apq_backend=PostgreSQLBackend(),
# Tenant context extracted from JWT automatically
)
# That's it! Multi-tenant APQ is ready.
# Request with JWT containing tenant_id
POST /graphql
Authorization: Bearer eyJ...
{
"query": "{ users { id name } }",
"extensions": {
"persistedQuery": {
"version": 1,
"sha256Hash": "abc123..."
}
}
}
# FraiseQL automatically:
# 1. Extracts tenant_id from JWT
# 2. Creates composite cache key: (query_hash, tenant_id)
# 3. Ensures tenant A never sees tenant B's cached data
# 4. Returns results in 0.5-2ms
# Option 1: PostgreSQL Backend (recommended)
from fraiseql.storage.backends import PostgreSQLBackend
apq_backend = PostgreSQLBackend()
# Option 2: Memory Backend (fast, single-server)
from fraiseql.storage.backends import MemoryBackend
apq_backend = MemoryBackend(max_size=10000)
# Option 3: Redis Backend (distributed systems)
from fraiseql.storage.backends import RedisBackend
apq_backend = RedisBackend(redis_url="redis://localhost")
# All backends support multi-tenant isolation
0.5-2ms cached query execution. 10-25x faster than parsing GraphQL every time.
Tenant isolation via composite cache keys. Prevents cross-tenant data leakage automatically.
PostgreSQL backend stores cached queries in your database. Fewer moving parts in production.
Send query hash instead of full GraphQL query. Massive savings for large queries.
tenant_id extracted from JWT metadata automatically. Zero configuration needed.
Achievable in production with stable query patterns. Typical: 85-95% for dynamic applications.
from fraiseql.fastapi import create_app
from fraiseql.storage.backends import PostgreSQLBackend
# Custom tenant extraction
def extract_tenant_id(context):
"""Extract tenant_id from custom JWT claim"""
return context.request.state.user.organization_id
app = create_app(
database_url="postgresql://localhost/db",
apq_backend=PostgreSQLBackend(
tenant_extractor=extract_tenant_id,
max_cache_size=50000, # Limit cached queries
ttl=3600, # 1 hour cache expiration
),
enable_apq_logging=True, # Track cache hits/misses
)
# Monitor APQ performance
@app.get("/metrics/apq")
async def apq_metrics():
stats = await app.state.apq_backend.get_stats()
return {
"cache_hit_rate": stats.hit_rate,
"total_queries": stats.total,
"cached_queries": stats.cached,
}
| Feature | Traditional APQ | FraiseQL APQ |
|---|---|---|
| Multi-Tenant Isolation | ❌ Manual implementation | ✅ Built-in via composite keys |
| Storage Backend | Redis/Memcached required | ✅ PostgreSQL, Memory, or Redis |
| JWT Integration | Manual tenant extraction | ✅ Automatic from context |
| Configuration | Complex setup | ✅ Zero-config default |
| Security Guarantees | Developer responsibility | ✅ Framework-enforced isolation |
APQ with multi-tenant isolation is available in FraiseQL v0.9.3+