Skip to content

Conversation

@roncodes
Copy link
Member

Problem

Critical Bug: Different API queries with different filter parameters were generating identical cache keys, causing data integrity issues where users received cached results from other queries.

Example

/int/v1/contacts?page=1&sort=-created_at&type=customer
/int/v1/contacts?page=1&sort=-created_at&type=contact

Both queries generated the same cache key: {api_query}:contacts:company_xxx:v1:71931a6d2abd2d6c69b7ec6290dd3361

This meant users requesting type=contact could receive cached results from type=customer queries, and vice versa.

Root Cause

The generateQueryCacheKey() method in ApiModelCache.php only included a hardcoded whitelist of 11 parameters:

$params = [
    'limit', 'offset', 'page', 'sort', 'order', 
    'query', 'search', 'filter', 'with', 'expand', 'columns'
];

Any filter parameters not in this list (like type, status, category, etc.) were ignored in cache key generation.

Solution

Changed from a hardcoded whitelist to including all query parameters in the cache key:

// Get ALL query parameters from the request
$params = $request->query();

// Remove only internal/cache-busting parameters
$excludedParams = ['_', 'timestamp', 'nocache', '_method'];

Impact

Fixes data integrity issue - Different queries now generate different cache keys
Accurate cache behavior - HIT/MISS status now reflects actual query uniqueness
Backward compatible - Existing cache keys will naturally expire and regenerate
No breaking changes - Cache mechanism remains unchanged

Testing

Verified with test cases:

  • type=customer hash: 333e10182061e4f35013c092e7524789
  • type=contact hash: bad2d03c864b9474d63bb155dc8e8d08
  • Hashes are now different

Deployment Notes

After deploying this fix:

  1. Existing cache entries will naturally expire based on TTL (5 minutes for queries)
  2. No manual cache flush required
  3. Monitor X-Cache-Status header to verify correct HIT/MISS behavior
  4. Consider flushing Redis cache if immediate fix is needed: redis-cli FLUSHDB

Files Changed

  • src/Support/ApiModelCache.php - Updated generateQueryCacheKey() method

Related Issues

This fix addresses cache key collisions for any filter parameters not in the original hardcoded list.

…in cache key

Previously, generateQueryCacheKey() only included a hardcoded whitelist of 11 parameters,
causing cache key collisions when different filter values were used (e.g., type=customer
vs type=contact generated the same cache key).

This fix includes ALL query parameters in the cache key generation, excluding only
internal/cache-busting parameters like '_', 'timestamp', 'nocache', and '_method'.

Impact:
- Fixes data integrity issue where different queries returned cached results from other queries
- Ensures accurate cache HIT/MISS behavior for all filter combinations
- Backward compatible - existing cache keys will naturally expire and regenerate

Example:
Before: /contacts?type=customer and /contacts?type=contact had SAME cache key
After:  /contacts?type=customer and /contacts?type=contact have DIFFERENT cache keys
@roncodes roncodes changed the base branch from main to dev-v1.6.30 December 21, 2025 03:46
@roncodes roncodes merged commit 42a2335 into dev-v1.6.30 Dec 21, 2025
1 check passed
@roncodes roncodes deleted the dev-v1.6.29 branch December 21, 2025 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants