HybridCache API
Description
In the description for HybridCache it says that it "bridges some gaps in the existing IDistributedCache and IMemoryCache APIs". However it also seems to create some new gaps - especially for existing applications which want to use the new HybridCache capability.
What I am referring is that both IDistributedCache and IMemoryCache APIs provided synchronous methods for interacting with the cache:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache?view=net-9.0-pp https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.memory.imemorycache?view=net-9.0-pp
Based on the public messaging, HybridCache is being positioned as a "drop-in replacement" for IDistributedCache and IMemoryCache. However if an application is utilizing the synchronous methods of either of these APIs, then it is not a "drop-in replacement" to use HybridCache in its current form - it may actually require significant refactoring of an application to conform to the asynchronous approach (which may not even be feasible if there are downstream consumers depending on the existing synchronous APIs). This could severely limit adoption for the new HybridCache... as faced with a large-scale refactoring effort, developers may decide to stay on the older IDistributedCache or IMemoryCache options.
I have reviewed the design discussions on GitHub related to HybridCache and I am surprised that this "gap" in functionality was not raised previously. Perhaps the problem was that the community was only thinking about HybridCache in a theoretical sense and not considering how they would integrate it into their existing applications. Regardless, there are a few comments about the current API approach on GitHub:
“The fact that we're caching means we can reasonably assume this operation will be non-trivial, and possibly one or both of an an out-of-process backend store call (with non-trivial payload) and an underlying data fetch (with non-trivial total time); async is strongly desirable.”
“Intentionally not providing sync API because why are you caching if it's fast enough to do inline?”
These are both valid comments. And if someone was building a new green-field application then it absolutely makes sense that they should use an asynchronous approach. But for existing .NET Core applications, many are still using synchronous patterns.
For example if we consider this very simple caching pattern wrapping an EF Core repository method using IMemoryCache:
public IEnumerable<Alias> GetItems()
{
return _cache.GetOrCreate("items", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return _db.Item.ToList();
});
}
HybridCache does not provide a GetOrCreate() synchronous method... which means that the GetItems() method would need to be refactored to be async... and any consumers of this method would also need to become async... which produces a very disruptive ripple effect when the original goal was simply to use HybridCache.
I do understand that one of Microsoft's goals is to prevent developers from "shooting themselves in the foot". And allowing a developer to use a synchronous cache method to wrap a call to an out-of-process backend store could lead to scalability or performance problems in some scenarios. However, completely removing this capability has other ramifications - especially for migrating existing applications.
@mgravell Since HybridCache is currently still in preview and is expected to be officially released in a future minor release of .NET Extensions, would it be possible to consider expanding the API to include some synchronous methods to fill these gaps and allow it to truly be a "drop in replacement" for IDistributedCache and IMemoryCache?
Reproduction Steps
Attempt to integrate HybridCache into an existing application where synchronous cache methods are being used from IDistributedCache or IMemoryCache
Expected behavior
HybridCache API should have synchronous methods equivalent to IDistributedCache and IMemoryCache
Actual behavior
Requires significant refactoring of existing code in order to integrate HybridCache - which is not even feasible in some cases
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
No response
I think the implementation is in preview (part of Microsoft.Extensions), while the abstraction is already final (part of .NET 9), but maybe I'm wrong.
Meanwhile you can take a look at FusionCache which supports sync+async (shameless plug).
Hope this helps.
@mgravell When will HybridCache no longer be classified as "in preview"... and is there a possibility that the API will be enhanced to support synchronous methods (ie. to provide a simpler migration path for developers)?
Working on the first right now.
On the second: short answer "yes"; longer answer "it is complicated" - putting the additional methods in the abstraction requires a higher "bar" re our API change process, so I basically have three options:
- wait until .NET 10 for those additions
- add an additional public concrete type in the implementation assembly to allow me add it via type-testing
- add it via some kind of extension method with type-testing
I'm working on the design options for all of these.
@mgravell is there any chance that HybridCache will be enhanced with sync methods in a future .NET iteration... or is it better to use an alternative such as FusionCache?
@sbwalker I can't offer a qualified opinion - I was part of the cull mid-2025.
@mgravell my condolences (I was not aware)
I have started using FusionCache because of lack of synchronous methods in HybridCache and am very satisfied with the library.