Cache-Aside Pattern in Python: Per-Service Mock

A Python mock of the cache-aside pattern for a single microservice—lazy-load from a database into an in-memory cache and invalidate on updates.

Easy Python 3.9+ Aug 9, 2026 Microservices patterns 12 views 0 copies

Python code

34 lines
Python 3.9+
class ServiceCache:
    def __init__(self):
        self.database = {"user:1": "Alice", "user:2": "Bob", "user:3": "Charlie"}
        self.cache = {}

    def get_user(self, user_id):
        cache_key = f"user:{user_id}"
        if cache_key in self.cache:
            print(f"CACHE HIT: {cache_key}")
            return self.cache[cache_key]

        print(f"CACHE MISS: {cache_key}, loading from database")
        user = self.database.get(cache_key)
        if user:
            self.cache[cache_key] = user
        return user

    def update_user(self, user_id, new_name):
        cache_key = f"user:{user_id}"
        self.database[cache_key] = new_name
        self.cache.pop(cache_key, None)
        print(f"UPDATED {cache_key}, invalidated cache")


if __name__ == "__main__":
    service = ServiceCache()

    print("First read (cache miss):", service.get_user(1))
    print("Second read (cache hit):", service.get_user(1))
    print("Third read (cache hit):", service.get_user(1))

    service.update_user(1, "Alice Smith")
    print("After update (cache miss):", service.get_user(1))
    print("After update (cache hit):", service.get_user(1))

Output

stdout
First read (cache miss): CACHE MISS: user:1, loading from database
Alice
Second read (cache hit): CACHE HIT: user:1
Alice
Third read (cache hit): CACHE HIT: user:1
Alice
UPDATED user:1, invalidated cache
After update (cache miss): CACHE MISS: user:1, loading from database
Alice Smith
After update (cache hit): CACHE HIT: user:1
Alice Smith

How it works

The ServiceCache class wraps a simulated database dict and an in-memory cache dict. Reads implement cache-aside: check the cache first; on a miss, load from the database and populate the cache. Writes update the source of truth and invalidate the stale cache entry, ensuring the next read is a miss and fetches fresh data. The cache-key prefix user: keeps the mock realistic and readable. This design isolates caching logic per service, which matches microservice boundaries.

Common mistakes

  • Forgetting to invalidate the cache on writes, causing stale reads.
  • Only implementing cache-aside for reads but not handling cache invalidation on updates.
  • Using a global cache across services instead of a per-service cache, creating cross-service coupling.

Variations

  1. Use a TTL (time-to-live) on cache entries and treat expired keys as misses.
  2. Replace the in-memory dict with redis or memcached for a distributed cache.

Real-world use cases

  • A user profile service that caches frequently-read records to reduce database load in production.
  • An order service that invalidates the cache line item data whenever inventory changes.
  • A pricing service that caches computed quotes and clears them on price updates.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Microservices patterns

Related tutorials and quizzes for this topic.