Skip to main content

Overview

FKApi uses Redis as the caching backend to improve performance by reducing database queries and API response times. The caching system includes automatic invalidation via Django signals, cache warming capabilities, and configurable TTL values.

Cache Configuration

Redis Setup

Location: fkapi/settings.py
Environment Variables:
  • REDIS_URL - Redis connection URL (default: redis://localhost:6379/1)

Cache Timeouts

Different cache timeouts for different data types:

Cache Key Generation

generate_cache_key()

Location: core/cache_utils.py:30-52
Features:
  • Consistent key format from prefix and arguments
  • Automatically sorts keyword arguments for consistency
  • Hashes keys longer than 200 characters using MD5
  • Prevents Redis key length issues
Implementation:

Cached Endpoints

Clubs

GET /api/clubs//kits

  • Cache key: club_kits_{club_id}_season_{season}_page_{page}_page_size_{page_size}
  • TTL: 30 minutes (CACHE_TIMEOUT_MEDIUM)
  • Implementation: fkapi/api.py:603-619
  • Invalidation: When Kit, Club, or Season changes

GET /api/clubs/search

  • Cache key: search_clubs_{keyword}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:650-661
  • Invalidation: When Club changes

Kits

GET /api/kits

  • Cache key: kits_club_{club}_season_{season}_country_{country}_primary_color_{color}_secondary_color_{colors}_design_{design}_year_{year}_first_year_{fy}_second_year_{sy}_page_{page}_page_size_{size}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:982-1022
  • Invalidation: When Kit changes

GET /api/kits/

  • Cache key: kit_json_{kit_id}
  • TTL: 1 hour (CACHE_TIMEOUT_LONG)
  • Implementation: fkapi/api.py:1446-1529
  • Invalidation: When Kit changes

GET /api/kits/bulk

  • Cache key: kits_bulk_{sorted_slugs_csv}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:1364-1407
  • Invalidation: When Kit changes

GET /api/kits/search

  • Cache key: search_kits_{keyword}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:1265-1285
  • Invalidation: When Kit changes

Seasons

GET /api/seasons

  • Cache key: season_club_{club_id}
  • TTL: 1 hour
  • Implementation: fkapi/api.py:1053-1066
  • Invalidation: When Club or Kit changes

GET /api/seasons/search

  • Cache key: search_seasons_{keyword}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:1159-1168
  • Invalidation: When Season changes

Brands

GET /api/brands/search

  • Cache key: search_brands_{keyword}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:690-709
  • Invalidation: When Brand changes

Competitions

GET /api/competitions/search

  • Cache key: search_competitions_{keyword}
  • TTL: 30 minutes
  • Implementation: fkapi/api.py:738-760
  • Invalidation: When Competition changes

User Collections

GET /api/user-collection/

  • Cache key: user_collection_{userid}
  • TTL: 7 days (604800 seconds)
  • Implementation: fkapi/api.py:1817-1851
  • Invalidation: Manual via force=true parameter

Cache Invalidation

Automatic Invalidation

Location: core/cache_utils.py:196-217 Cache invalidation is triggered automatically via Django signals when models are saved or deleted. Signal Setup:

Cache Invalidation Functions

Location: core/cache_utils.py

invalidate_club_cache()

Invalidates (cache_utils.py:54-67):
  • club_{club_id}_*
  • season_club_{club_id}_*
  • kit_club_{club_id}_*
  • search_club_{club_id}_*

invalidate_season_cache()

Invalidates (cache_utils.py:70-82):
  • season_{season_id}_*
  • kit_season_{season_id}_*
  • search_season_{season_id}_*

invalidate_kit_cache()

Invalidates (cache_utils.py:85-96):
  • kit_{kit_id}_*
  • search_kit_{kit_id}_*
  • Related club and season caches (via _invalidate_kit_related)

invalidate_brand_cache()

Invalidates (cache_utils.py:99-110):
  • brand_{brand_id}_*
  • search_brand_{brand_id}_*

invalidate_competition_cache()

Invalidates (cache_utils.py:113-124):
  • competition_{competition_id}_*
  • search_competition_{competition_id}_*

invalidate_search_cache()

Invalidates (cache_utils.py:127-134):
  • search_* (all search-related caches)

invalidate_user_collection_cache()

Invalidates (cache_utils.py:137-148):
  • user_collection_{userid}

Pattern-Based Invalidation

Location: core/cache_utils.py:151-178
Features:
  • Uses Redis KEYS command for pattern matching
  • Includes fkapi: key prefix automatically
  • Gracefully handles unsupported cache backends
  • Logs invalidation actions

Cache Warming

Cache warming pre-populates frequently accessed data to improve response times.

Management Command

Command: python manage.py warm_cache Options:

Examples

Cache seasons for top 100 clubs:
Cache 200 recent kits:
Cache everything including popular searches:

Scheduled Warming with Celery

Add cache warming to your Celery beat schedule:

Performance Optimization

Query Optimization

Cached endpoints use optimized queries:
Benefits:
  • select_related() - Reduces queries for foreign keys (single JOIN)
  • prefetch_related() - Efficient queries for many-to-many relationships
  • Combined: Minimize database round-trips

Cache Hit Rate Monitoring

Monitor cache performance via Redis:
Calculate hit rate:
Target: 80%+ hit rate for optimal performance Low hit rates may indicate:
  • Timeouts too short
  • Cache invalidation too frequent
  • Need for cache warming
  • Unique queries (not cacheable)

Memory Management

Redis Configuration (redis.conf):
Monitor memory usage:
Key metrics:
  • used_memory - Total memory used
  • used_memory_peak - Peak memory usage
  • used_memory_overhead - Overhead memory
  • evicted_keys - Number of evicted keys

Cache Flow Diagram

Troubleshooting

Cache Not Working

1. Verify Redis is running:
2. Test Django cache connection:
3. Check django-redis installation:
4. Verify environment variables:

Stale Data Issues

Symptoms:
  • Updated data not reflected in API responses
  • Old data returned after model changes
Solutions: 1. Verify signal connections:
2. Check signal firing:
3. Manual cache invalidation:
4. Check cache timeouts:

High Memory Usage

1. Check Redis memory:
2. View cache keys:
3. Reduce cache timeouts:
4. Implement cache size limits:
5. Clean up unused keys:

Best Practices

1. Use Consistent Cache Keys

Always use generate_cache_key() for consistency:

2. Set Appropriate Timeouts

Match timeout to data change frequency:

3. Monitor Cache Performance

Metrics to track:
  • Cache hit rate (target: 80%+)
  • Average response time
  • Database query count
  • Redis memory usage
  • Cache key count
Tools:
  • Redis INFO command
  • Django Debug Toolbar
  • Application Performance Monitoring (APM)

4. Warm Cache After Deployments

5. Test Cache Invalidation