Cache-Aside

1. The Problem

You've got an ASP.NET Core ProductService running in Azure.

A customer requests:

GET /products/123

Your API goes to the database, gets the product, and returns it.

Seems fine, right?

Now imagine the same product is requested thousands of times.

Every request goes all the way to the database, even though the product information hasn't changed.

The flow looks like this:

Customer
   |
   v
ASP.NET Core API
   |
   v
Database
   |
   v
Product 123

The database is doing the same work again and again.

For frequently requested data, that's unnecessary.

You need a faster place to keep a temporary copy of data that is accessed often.

That's where a cache comes in.


2. What's Actually Going Wrong?

The problem isn't necessarily that your database is slow.

The problem is that you're repeatedly asking the database for the same data.

For example:

Product 123
Product 123
Product 123
Product 123
Product 123
...

If Product 123 hasn't changed, why keep going to the database?

You can keep a copy of frequently accessed data in a distributed cache such as Azure Managed Redis.

Now the request can potentially be served like this:

Customer
   |
   v
ASP.NET Core API
   |
   v
Azure Managed Redis
   |
   v
Product 123

But there is an important question:

What happens when Product 123 isn't in the cache?

That's where Cache-Aside comes in.


3. The Concept

Cache-Aside is a caching pattern where the application manages the cache.

The application follows a simple flow:

  1. Check the cache first.
  2. If the data is there, return it.
  3. If the data isn't there, query the database.
  4. Put the result into the cache.
  5. Return the result.

The basic flow

                  +------------------+
                  |      Request     |
                  +--------+---------+
                           |
                           v
                  +------------------+
                  |  ASP.NET Core    |
                  |      API         |
                  +--------+---------+
                           |
                           v
                  +------------------+
                  |      Cache       |
                  +--------+---------+
                           |
                    +------+------+
                    |             |
                   HIT           MISS
                    |             |
                    v             v
               Return data    Query database
                                  |
                                  v
                           Put data in cache
                                  |
                                  v
                              Return data

The important idea is:

The cache is not the source of truth.

The database remains the source of truth.

The cache is simply a faster copy of data that the application expects to access frequently.


4. How Do You Fix It?

Same flow as before, with the generic "Cache" now a real Azure Managed Redis instance sitting between ASP.NET Core API and the database.

Here's what each branch actually looks like:

Cache HIT

Suppose Product 123 is already in Redis.

The request comes in:

Request
   |
   v
ASP.NET Core API
   |
   v
Redis
   |
   v
Product 123 found
   |
   v
Return response

The database isn't touched.

This is where the cache provides its biggest benefit.

Cache MISS

Now suppose Product 456 isn't in Redis.

The application checks the cache and doesn't find it.

So it goes to the database:

Request
   |
   v
ASP.NET Core API
   |
   v
Redis
   |
   | MISS
   v
Database
   |
   v
Product 456
   |
   +--------> Store in Redis
   |
   v
Return response

The next request for Product 456 can now be served from Redis.

This is the essence of Cache-Aside.

The application decides when to read from the cache and when to go to the database.

It also decides when data should be added to or removed from the cache.

One important point

Don't think of Cache-Aside as:

“Put everything in Redis.”

That's not the goal.

You typically cache data that is:

  • Frequently requested
  • Relatively expensive to retrieve
  • Reasonably stable
  • Acceptable to serve from a cached copy for some period

For example, product catalog information may be a good candidate.

Highly volatile or strongly consistent data may require a different approach.


5. What About Updates?

This is where caching gets interesting.

Suppose the database contains:

Product 123
Price = ₹1,200

But Redis still contains:

Product 123
Price = ₹999

Now you have stale data.

So caching isn't simply about putting data into Redis.

You also need a strategy for deciding how long cached data should remain valid.

TTL

A common approach is a TTL (Time To Live).

For example:

Product 123
     |
     v
Cache for 10 minutes
     |
     v
Expires
     |
     v
Next request
     |
     v
Database
     |
     v
Fresh value goes back into cache

This gives you a simple rule:

“This cached value is allowed to live for 10 minutes.”

For data where stale values are unacceptable, the application can explicitly invalidate or update the cache when the underlying data changes.

For example:

Update Product
      |
      v
Database updated
      |
      v
Invalidate cache
      |
      v
Next request
      |
      v
Cache MISS
      |
      v
Read fresh value from database
      |
      v
Populate cache

The exact strategy depends on the business requirement.

The important question is:

“How stale can this data be?”

If the answer is “it must never be stale,” you need to think much more carefully about whether a simple Cache-Aside approach is appropriate.


6. Visualize It in Everyday Terms

Imagine a restaurant manager.

The official menu and prices are maintained in the main office.

But the manager keeps the prices of the most popular dishes on a small card at the counter.

Why?

Because customers ask about those dishes all the time.

So:

  • Main office = Database
  • Counter card = Cache
  • Restaurant manager = Application

A customer asks:

“What's the price of the most popular dish?”

The manager checks the counter card first.

If the price is there, the manager gives the answer immediately.

That's a cache hit.

If the price isn't there, the manager goes to the main office, gets the latest price, puts it on the counter card, and gives the answer to the customer.

That's a cache miss.

The next customer asking the same question gets the answer from the card.

That's Cache-Aside.

And if the price changes in the main office, the manager needs to make sure the card doesn't continue showing the old price forever.

That's the stale data problem.


7. What Should You Remember?

Think about Cache-Aside as:

             REQUEST
                |
                v
          CHECK CACHE
           /        \
        HIT          MISS
         |             |
         v             v
    RETURN DATA    DATABASE
                       |
                       v
                 PUT IN CACHE
                       |
                       v
                  RETURN DATA

The five things to remember:

  1. Check the cache first.
  2. On a hit, return the cached data.
  3. On a miss, get the data from the database.
  4. Put the retrieved data into the cache.
  5. The database remains the source of truth.

And don't forget the sixth point:

Cached data can become stale.

So every caching design needs an appropriate expiration, invalidation, or refresh strategy.

The simplest mental model is:

Cache-Aside means the application checks the cache first, falls back to the database on a miss, and populates the cache with what it found.

8. .NET + Azure Context

Application: ASP.NET Core / .NET

Caching approach: Application-managed caching

Distributed cache: Azure Managed Redis

Source of truth: Database

Pattern: Cache-Aside

Main benefit: Reduce repeated database reads and improve response time

Main concern: Stale cached data

From a .NET engineer's perspective, the important mental model is not:

“How do I use Redis?”

It is:

“Where should I look first, what do I do when it's not there, and how do I keep the cached copy from becoming a problem?”
That's Cache-Aside.