Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Design a comprehensive caching system that speeds up reads, reduces database load, and keeps data reasonably fresh. Not "add Redis everywhere" — specific cache layers, TTL strategies, invalidation patterns, and cost-benefit analysis.
Purpose: Cache static assets (JS, CSS, images) on user's device Storage: User's browser TTL: 30 days for versioned assets, 5 minutes for HTML Size Limit: ~50 MB per domain Control: HTTP headers (Cache-Control, ETag)
Layer 2: CDN (Content Delivery Network)
Purpose: Cache static and dynamic content close to users Storage: CloudFlare, Fastly, AWS CloudFront TTL: 1 hour for API responses, 1 day for assets Size Limit: Unlimited (CDN-dependent) Control: HTTP headers + CDN purge API
Layer 3: Application Cache (Redis/Memcached)
Purpose: Cache database query results, computed data, session data Storage: Redis Cluster TTL: 30 seconds to 1 hour (data-dependent) Size Limit: 16 GB per instance (scale horizontally) Control: Application code
Layer 4: Database Query Cache
Purpose: Cache repeated queries at database level Storage: PostgreSQL query cache, MySQL query cache TTL: Automatic (invalidated on table write) Size Limit: 1-4 GB Control: Database configuration
What to Cache
High-Value Candidates
User Profile (Read-heavy, infrequent writes)
Current: Query database on every request
Cached: Store in Redis for 5 minutes
Impact: 1000 req/s → 5 DB queries/s (99.5% reduction)
TTL: 5 minutes (acceptable staleness)
Invalidation: Purge on profile update
Product Catalog (Read-heavy, daily updates)
Current: Query database for product list
Cached: Store in Redis for 1 hour
Impact: 500 req/s → 0.14 DB queries/s
TTL: 1 hour
Invalidation: Purge on product update
Homepage (Read-only, hourly updates)
Current: Render HTML on every request
Cached: Store rendered HTML in CDN for 5 minutes
Impact: 10,000 req/s → 33 origin requests/s
TTL: 5 minutes
Invalidation: Auto-expire + manual purge on content publish
Session Data (Read-heavy per user)
Current: Query database for session token validation
Cached: Store in Redis with JWT
Impact: Every authenticated request → 0 DB queries
TTL: 24 hours
Invalidation: Logout or token refresh
Low-Value Candidates (Don't Cache)
User Orders (Fresh data critical)
Why: Order status must be real-time
Alternative: Cache individual order if unchanged for 1 minute
Inventory Count (High write frequency)
Why: Changes on every purchase, cache would be stale
Alternative: Cache at 10-second granularity if acceptable
import time
defget_product_with_lock(product_id):
cache_key = f"product:{product_id}"
lock_key = f"lock:{cache_key}"# Check cache
cached = cache.get(cache_key)
if cached:
return json.loads(cached)
# Try to acquire lock
lock = cache.set(lock_key, "1", nx=True, ex=10)
if lock:
# This request rebuilds cache
product = db.query(Product).filter(Product.id == product_id).one()
cache.setex(cache_key, 3600, json.dumps(product.to_dict()))
cache.delete(lock_key)
return product.to_dict()
else:
# Another request is rebuilding, wait and retry
time.sleep(0.1)
return get_product_with_lock(product_id) # Retry
4. Tag-Based Invalidation
How: Tag cache entries, purge by tag When: Need to invalidate related items Example: Invalidate all caches for user's orders
# Store with tag
cache.set("order:123", order_data, tags=["user:xyz", "orders"])
# Invalidate by tag
cache.invalidate_tag("user:xyz") # Clears all user's data
Cache Warming
On Application Start
defwarm_cache():
"""Pre-populate cache with hot data"""# Top 100 products by sales
top_products = db.query(Product).order_by(Product.sales.desc()).limit(100)
for product in top_products:
cache.setex(f"product:{product.id}", 3600, json.dumps(product.to_dict()))
# Active users (logged in last 24h)
active_users = db.query(User).filter(User.last_login > datetime.now() - timedelta(days=1))
for user in active_users:
cache.setex(f"user:{user.id}", 300, json.dumps(user.to_dict()))
HTTP Caching Headers
Cache-Control
Cache-Control: public, max-age=3600
public — Can be cached by CDN and browser
private — Browser only (not CDN)
max-age=3600 — Cache for 1 hour
no-cache — Must revalidate with server
no-store — Never cache (sensitive data)
ETag (Entity Tag)
Response:
ETag: "abc123"
Next request:
If-None-Match: "abc123"
Response:
304 Not Modified (if ETag matches)
Use: Validate if content changed without re-downloading
Problem: User A sees User B's data Solution: Include user ID in cache key: user:{user_id}:orders
Testing Cache Strategy
Unit Tests
deftest_cache_hit():
cache.set("user:123", user_data)
result = get_user("123")
assert result == user_data
assert db_mock.call_count == 0# DB not querieddeftest_cache_miss():
cache.delete("user:123")
result = get_user("123")
assert db_mock.call_count == 1# DB queried
Load Tests
Simulate 10,000 requests with cache enabled
Compare latency vs without cache
Verify 80%+ hit rate
Rules
Cache key must be unique and predictable: {resource}:{id} format (e.g., user:123, product:abc).
TTL must be set for every cache entry — infinite TTL = eventual stale data.
Cache invalidation must happen synchronously with writes — update DB then invalidate cache, not the reverse.
Always handle cache failures gracefully — app must work if Redis is down (degraded, not broken).
Hit rate below 70% means caching wrong data or TTL too short.
Include user_id in cache key for user-specific data to prevent data leakage.
Never cache sensitive data (passwords, credit cards) even with short TTL.
Eviction rate > 100/sec means cache is undersized — increase memory or reduce TTL.
For high-write workloads (> 50% writes), caching may hurt more than help — benchmark first.
Cache warming is optional for small datasets, mandatory for large datasets to prevent cold-start stampede.