{"id":6326,"library":"cashews","title":"Cashews","description":"Cashews is a Python library providing asynchronous cache tools, designed to help build fast and reliable applications. It supports multiple storage backends like in-memory, Redis, and DiskCache, offering a decorator-based API and various caching strategies. The current version is 7.5.0, and it maintains an active release cadence with regular updates and community support.","status":"active","version":"7.5.0","language":"en","source_language":"en","source_url":"https://github.com/Krukov/cashews/","tags":["caching","async","redis","diskcache","decorators","performance"],"install":[{"cmd":"pip install cashews","lang":"bash","label":"Standard Installation"},{"cmd":"pip install cashews[redis]","lang":"bash","label":"With Redis Backend"},{"cmd":"pip install cashews[diskcache]","lang":"bash","label":"With DiskCache Backend"},{"cmd":"pip install cashews[speedup]","lang":"bash","label":"With Performance Optimizations (xxhash, bitarray, hiredis)"},{"cmd":"pip install cashews[dill]","lang":"bash","label":"With Dill for more object types in Redis"}],"dependencies":[{"reason":"Requires Python 3.10 or higher.","package":"python","optional":false},{"reason":"Optional, required for Redis backend functionality.","package":"redis","optional":true},{"reason":"Optional, required for DiskCache backend functionality.","package":"diskcache","optional":true},{"reason":"Optional, for enhanced serialization of more object types in Redis.","package":"dill","optional":true},{"reason":"Optional, for improved hashing algorithms (e.g., in Bloom filters or digestmod).","package":"xxhash","optional":true},{"reason":"Optional, for speedup with Bloom filters.","package":"bitarray","optional":true},{"reason":"Optional, for faster Redis parsing.","package":"hiredis","optional":true}],"imports":[{"symbol":"cache","correct":"from cashews import cache"}],"quickstart":{"code":"import asyncio\nimport os\nfrom datetime import timedelta\n\nfrom cashews import cache\n\n# Configure Redis cache. Replace with your Redis URL or use \"mem://\" for in-memory.\n# For production, use environment variables for connection strings.\nREDIS_URL = os.environ.get(\"CASHEWS_REDIS_URL\", \"redis://localhost:6379/0\")\ncache.setup(REDIS_URL, client_side=True)\n\n@cache(ttl=timedelta(minutes=5), key=\"user:{user_id}\")\nasync def get_user_data(user_id: int):\n    \"\"\"\n    Simulates a long-running operation to fetch user data.\n    This function's result will be cached.\n    \"\"\"\n    print(f\"Fetching data for user_id: {user_id} from source...\")\n    await asyncio.sleep(1) # Simulate I/O delay\n    return {\"id\": user_id, \"name\": f\"User {user_id}\", \"email\": f\"user{user_id}@example.com\"}\n\nasync def main():\n    print(\"First call (should fetch from source):\")\n    user1_data = await get_user_data(1)\n    print(f\"Result: {user1_data}\")\n\n    print(\"\\nSecond call (should hit cache):\")\n    user1_data_cached = await get_user_data(1)\n    print(f\"Result: {user1_data_cached}\")\n\n    print(\"\\nFetching data for a different user (should fetch from source):\")\n    user2_data = await get_user_data(2)\n    print(f\"Result: {user2_data}\")\n\n    # Example of explicit cache invalidation:\n    # await cache.invalidate(get_user_data, user_id=1)\n    # print(\"\\nAfter invalidation, first call again (should fetch from source):\")\n    # user1_data_recalled = await get_user_data(1)\n    # print(f\"Result: {user1_data_recalled}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates setting up Cashews with a Redis backend (or in-memory if Redis is unavailable) and using the `@cache` decorator for an asynchronous function. It shows how subsequent calls to the cached function with the same arguments will retrieve data from the cache rather than re-executing the heavy operation."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or higher, or pin Cashews to a version older than 7.5.0 (e.g., `cashews<7.5.0`).","message":"Cashews dropped support for Python 3.9 starting from version 7.5.0. Ensure your project uses Python 3.10 or newer.","severity":"breaking","affected_versions":">=7.5.0"},{"fix":"Always specify `ttl` (e.g., `ttl=\"1h\"`, `ttl=timedelta(hours=1)`) when defining a cache decorator or calling `cache.set()` and similar methods.","message":"The `ttl` (time-to-live) parameter is mandatory for all cache decorators and direct cache operations to prevent unbounded storage growth and ensure proper cache invalidation. Failing to provide `ttl` can lead to memory or storage overflow.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Configure `cache.setup()` with `secret` and `digestmod` (e.g., `cache.setup(..., secret='your_secret_key', digestmod='sha256')`) to protect against tampering. For more complex types, consider `dill` (install `cashews[dill]`).","message":"When using Redis, Cashews defaults to `pickle` for serializing values. While convenient, `pickle` can have security implications with untrusted data and may not serialize all object types. It's recommended to use the `secret` and `digestmod` parameters for enhanced security, or consider other serialization options if available.","severity":"gotcha","affected_versions":"All versions with Redis backend"},{"fix":"Prefer using Cashews' tag system for cache invalidation, which is designed for more efficient targeted invalidation with Redis.","message":"Using wildcard patterns (e.g., `\"items:page:*\"`) with `cache.invalidate()` when connected to a Redis backend can be inefficient. This operation might scan the entire Redis database, leading to performance issues on large datasets.","severity":"gotcha","affected_versions":"All versions with Redis backend"},{"fix":"Upgrade Cashews to version 7.4.4 or newer to benefit from the fix. If upgrading is not possible, ensure proper ContextVar management within your asynchronous code, particularly in frameworks that heavily rely on context switching.","message":"In earlier versions (prior to 7.4.4), improper cross-context usage of Cashews could lead to `ContextVar LookupError`. This typically occurs in complex asynchronous applications where contexts are not managed correctly.","severity":"gotcha","affected_versions":"<7.4.4"},{"fix":"Always use Cashews' API (`cache.set()`, `cache.delete()`, `cache.invalidate()`) for all cache modifications when client-side caching is enabled to ensure consistency across all layers. Avoid direct manipulation of cached keys in Redis via external tools or clients.","message":"When utilizing Redis client-side caching with Cashews, manually modifying or expiring keys in Redis directly (e.g., via `redis-cli`) will invalidate the client-side cache for those keys, but Cashews' internal state might not immediately reflect these external changes if not managed carefully. This can lead to unexpected cache misses or stale data if not properly accounted for.","severity":"gotcha","affected_versions":"All versions with Redis client-side caching"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z"}