Entity Framework Core - Caching L1 & L2
Caching in Entity Framework (EF) is a technique used to store data in memory to minimize database traffic and improve application performance. By reducing the number of round-trips to the database, you can significantly speed up data retrieval.
There are two distinct levels of caching in Entity Framework: First-Level (L1) and Second-Level (L2).
1. First-Level Caching (L1)
Scope: Per DbContext Instance
Status: Built-in and Enabled by Default
First-level caching is integral to how Entity Framework operates. It acts as a transaction buffer and an identity map.
How it works: When you query the database for an entity (e.g.,
Userwith ID 1), theDbContextstores that entity in its internal memory. If you request the same entity again within the sameDbContextlifespan, EF will return the entity from memory rather than querying the database again.Identity Resolution: It ensures that within a single context, only one object instance exists for a specific database record. This prevents inconsistencies where you might have two different objects representing the same row in the database.
Lifetime: The cache is destroyed as soon as the
DbContextis disposed. In a typical web application, this means the cache lives only as long as the HTTP request.
Note: You can bypass L1 caching using
.AsNoTracking(). This is useful for "read-only" scenarios where you don't need to update the data, making the query faster and using less memory.
2. Second-Level Caching (L2)
Scope: Global / Application-wide
Status: Requires Third-Party Configuration (in EF Core)
Second-level caching stores data across all DbContext instances. If User A retrieves a list of products, and then User B requests the exact same list, L2 caching allows User B to receive the data from the cache (e.g., Redis, Memory) without touching the database.
How it works: When a query is executed, an interceptor checks the cache provider (like Redis or in-memory cache).
Cache Hit: If the results are found, they are returned immediately.
Cache Miss: The query is executed against the database, and the results are then stored in the cache for future requests.
Implementation: Unlike L1, L2 caching is not built-in directly to the core of EF Core. You typically need to use a library (such as
EFCoreSecondLevelCacheInterceptor) to enable this functionality.
Key Differences at a Glance
| Feature | First-Level (L1) | Second-Level (L2) |
| Scope | Local (Current DbContext instance) | Global (Application-wide) |
| Duration | Request/Context lifespan | Configurable (minutes, hours, etc.) |
| Purpose | Consistency & Transaction Integrity | Performance & Load Reduction |
| Setup | Automatic (No setup required) | Manual (Requires external library) |
| Storage | Application Memory (RAM) | Memory, Redis, SQL Server, etc. |
When to Use Which?
Rely on L1 Caching when:
You are performing transactional updates.
You need to load an entity, modify it, and save it within a single request.
You want to ensure you are working with the absolute latest data during a complex operation.
Implement L2 Caching when:
You have data that changes infrequently (e.g., Country lists, Categories, Configuration settings).
You have high-traffic "read" pages where the database is becoming a bottleneck.
You are okay with slight data staleness (e.g., a user might see a product price update 5 minutes late).
Summary
L1 is about correctness and managing the transaction scope.
L2 is about speed and offloading work from the database server.

