Registry / database / async-cache

async-cache

JSON →
library2.0.3pypypi✓ verified 83d ago

async-cache is an asyncio application layer cache and dataloader for Python-based microservices and applications. It provides features like thundering herd protection, cache warmup, invalidation, and metrics. The current version is 2.0.0, and releases appear to be infrequent, driven by new feature additions.

pip install async-cache
INSTALL
IMPORT
SIG · ASYNC-CACHE
A
async-cache
databasepythonv2.0.3
Install
1.5s avg
Import
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.0.3 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.000s · 17.8MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 1.5s · import 0.000s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

AsyncCache
from cache import AsyncCache
from async_cache import AsyncCache

This quickstart demonstrates basic asynchronous caching with `AsyncCache` and its `InMemoryCacheBackend`, showcasing how to decorate an async function to cache its results. It also includes an example of `DataLoader` from version 2.0.0, illustrating how to batch requests for multiple items into a single backend call, effectively preventing N+1 problems in async applications.

import asyncio import time from async_cache import AsyncCache, InMemoryCacheBackend, DataLoader # --- Basic Caching Example --- async def run_basic_cache_example(): print("--- Basic Caching Example ---") # Initialize an in-memory cache backend cache_backend = InMemoryCacheBackend() # Set a default TTL of 60 seconds for cache entries cache = AsyncCache(cache_backend=cache_backend, default_ttl=60) @cache.cache(key="my_expensive_function:{arg1}") async def expensive_function(arg1: int, arg2: str) -> str: print(f"Executing expensive_function with {arg1}, {arg2}...") await asyncio.sleep(1) # Simulate network call or heavy computation return f"Result for {arg1}, {arg2} at {time.time()}" print("First call (should execute function):") result1 = await expensive_function(1, "hello") print(f"Result 1: {result1}") print("\nSecond call (should be cached, no function execution):") result2 = await expensive_function(1, "hello") print(f"Result 2: {result2}") print("\nThird call (different args, not cached, executes function):") result3 = await expensive_function(2, "world") print(f"Result 3: {result3}") # --- DataLoader Example (v2 feature) --- async def run_dataloader_example(): print("\n--- Dataloader Example ---") # A batch function that fetches multiple items efficiently async def fetch_users_batch(user_ids: list[int]) -> list[str]: print(f"Fetching users for IDs: {user_ids}") await asyncio.sleep(0.5) # Simulate batch API call return [f"User_{uid}_data" for uid in user_ids] # Initialize a dataloader with the batch function # The dataloader will collect individual load calls and batch them user_loader = DataLoader(batch_function=fetch_users_batch) async def get_user_data(user_id: int) -> str: return await user_loader.load(user_id) print("Calling get_user_data for multiple IDs (some duplicated):") # The dataloader will ensure fetch_users_batch is called only once for [1, 2, 3] results = await asyncio.gather( get_user_data(1), get_user_data(2), get_user_data(1), # This will be deduplicated by the dataloader get_user_data(3) ) print(f"Dataloader results: {results}") async def main(): await run_basic_cache_example() await run_dataloader_example() if __name__ == "__main__": asyncio.run(main())
Debug
Known issues
gotchaCache Key Specificity: Using overly broad or static cache keys can lead to incorrect cache hits or prevent dynamic data from being refreshed. Ensure keys are unique per unique set of arguments that determine the cached data.
fix
Use f-strings or explicit argument values in cache key definitions (e.g., `key="my_func:{arg1}:{arg2}"`) to ensure keys are sufficiently granular.
affects: All
gotchaAwaiting Cached Functions: Functions decorated with `@cache.cache` or accessed via `DataLoader.load()` must always be `await`ed, even if the result is a cache hit. Forgetting `await` will result in a coroutine object being returned, not the actual data.
fix
Always `await` calls to functions decorated with `@cache.cache` or accessed via `DataLoader`, e.g., `result = await my_cached_function(...)`.
affects: All
gotchaBackend Persistency: The `InMemoryCacheBackend` (used in examples) is not persistent across application restarts. For production environments requiring data to survive restarts, consider implementing or integrating a persistent cache backend (e.g., Redis).
fix
Understand `InMemoryCacheBackend`'s limitations; implement a custom persistent backend that integrates with `async-cache` for production use cases requiring data survival across restarts.
affects: All
Upgrade
Version history
2.0.3latest on PyPI · released Apr 22, 2026
Audit
Dependencies

No dependency data recorded yet.

Agent activity
30 hits · last 30 days
node
26
OpenAI (training)
1
Resources
async-cache — pip install async-cache · libregistry