A PostgreSQL Implementation of IDistributedCache interface. Using Postgresql as distributed cache in Asp.Net Core. NetStandard 2.0
- stars
- 81
- watchers
- 4
- forks
- 23
- open issues
- 26
- Last updated
- 10/31/2026
A PostgreSQL Implementation of IDistributedCache interface. Using Postgresql as distributed cache in Asp.Net Core. NetStandard 2.0
Community.Microsoft.Extensions.Caching.PostgreSQL is a robust and scalable distributed cache implementation for ASP.NET Core applications using PostgreSQL 11+ as the underlying data store. This package provides a simple and efficient way to leverage your existing PostgreSQL infrastructure for caching, offering a cost-effective alternative to dedicated caching servers. Ideal for scenarios where minimizing infrastructure complexity and maximizing performance is critical.
This library allows you to seamlessly integrate caching into your ASP.NET / .NET Core applications using the standard IDistributedCache interface. It's designed to be production-ready and configurable, giving you fine-grained control over caching behavior.
Why choose this package?
Install the package via the .NET CLI:
dotnet add package Community.Microsoft.Extensions.Caching.PostgreSql
Add the following line to your Startup.cs or Program.cs's ConfigureServices method:
services.AddDistributedPostgreSqlCache(setup => { setup.ConnectionString = configuration["ConnectionString"]; setup.SchemaName = configuration["SchemaName"]; setup.TableName = configuration["TableName"]; setup.DisableRemoveExpired = configuration["DisableRemoveExpired"]; // Optional - DisableRemoveExpired default is FALSE setup.CreateInfrastructure = configuration["CreateInfrastructure"]; // CreateInfrastructure is optional, default is TRUE // This means that every time the application starts the // creation of the table and database functions will be verified. setup.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30); // ExpiredItemsDeletionInterval is optional // This is the periodic interval to scan and delete expired items in the cache. Default is 30 minutes. // Minimum allowed is 5 minutes. - If you need less than this please share your use case 😁, just for curiosity... });
services.AddDistributedPostgreSqlCache((serviceProvider, setup) => { // IConfiguration is used as an example here var configuration = serviceProvider.GetRequiredService<IConfiguration>(); setup.ConnectionString = configuration["ConnectionString"]; ... });
Use:
services.AddDistributedPostgreSqlCache();
And implement and register:
IConfigureOptions<PostgreSqlCacheOptions>
When you have 2 or more instances/microservices/processes and you want to leave only one instance to remove expired items.
True, expired items will not be automatically removed. When calling GetItem, expired items are filtered out. In this scenario, you are responsible for manually removing the expired keys or updating them.If you (or the implementation using this cache) are explicitly calling IDistributedCache.Refresh to update the sliding window, you can turn off UpdateOnGetCacheItem to remove the extra DB expiration update call prior to reading the cached value. This is useful when used with ASP.NET Core Session handling.
services.AddDistributedPostgreSqlCache((serviceProvider, setup) => { ... setup.UpdateOnGetCacheItem = false; // Or var configuration = serviceProvider.GetRequiredService<IConfiguration>(); setup.UpdateOnGetCacheItem = configuration["UpdateOnGetCacheItem"]; ... });
For read-only databases, or if the database user lacks write permissions, you can set ReadOnlyMode = true.
services.AddDistributedPostgreSqlCache((serviceProvider, setup) => { ... setup.ReadOnlyMode = true; // Or var configuration = serviceProvider.GetRequiredService<IConfiguration>(); setup.ReadOnlyMode = configuration["UpdateOnGetCacheItem"]; ... });
This creates the table and schema for storing the cache (names are configurable) if they don't exist.
// This is extracted from the React+WebApi WebSample private readonly IDistributedCache _cache; public WeatherForecastController(IDistributedCache cache) { _cache = cache; } [HttpGet] public async Task<IEnumerable<WeatherForecast>> Get() { var cachedValue = await _cache.GetStringAsync("weather-forecast"); if(string.IsNullOrEmpty(cachedValue)) { //Do stuff to fetch data... var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); var byteArray = JsonSerializer.SerializeToUtf8Bytes(forecast); await _cache.SetAsync("weather-forecast", byteArray, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) }); return forecast; } var result = JsonSerializer.Deserialize<WeatherForecast[]>(cachedValue); return result; }
services.AddDistributedPostgreSqlCache((serviceProvider, setup) => { var configuration = serviceProvider.GetRequiredService<IConfiguration>(); setup.ConnectionString = configuration["CacheConnectionString"]; setup.SchemaName = "my_custom_cache_schema"; setup.TableName = "my_custom_cache_table"; setup.DisableRemoveExpired = true; setup.CreateInfrastructure = true; setup.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(15); setup.UpdateOnGetCacheItem = false; setup.ReadOnlyMode = true; });
You will need a local PostgreSQL server with the following:
postgres account, if not attached already to your user.PostgreSqlCacheSample:dotnet restore prepare-database.cmd -create dotnet run
You will need a local PostgreSQL server with the following:
postgres account, if not attached already to your user.npm and node installed on your development machine.WebSample directory:dotnet restore prepare-database.cmd -create // windows chmod +x prepare-database.sh // linux - just once to make the script executable ./prepare-database.sh -create // linux dotnet run
It may take some time for npm to restore the packages.
Then, you can delete the database using:
prepare-database.cmd -erase // windows ./prepare-database.sh -erase // linux
if you don't want to use the bash/cmd script, you can run the SQL script directly on your PostgreSQL database.
Option -create executes create-sample-database.sql
Option -erase executes erase-sample-database.sql
IHostApplicationLifetime if not supported on the platform (e.g., AWS) - issue #28Debug Level, multitarget .NET 5 and .NET 6, dropped support for netstandard2.0, fixed sample to match multi-targeting and sample database.CreateInfrastructure also creates the schema - issue #8DisableRemoveExpired configuration; if TRUE, the cache instance won't delete expired items.We welcome contributions! Please see our Contributing Guidelines for more details on how to get involved.
Q: What versions of PostgreSQL are supported?
A: This package supports PostgreSQL 11 and higher. For older versions (<= 10), use older versions of this package (<= 3.1.2).
Q: How do I handle database connection issues?
A: Ensure your connection string is correct and that your database server is accessible. Verify your username, password, and host settings.
Q: Is this package production-ready?
A: Yes, this package is designed for production use. It includes features like background expired item removal and configurable options, but it's always recommended to thoroughly test it in your specific environment.
Q: What are the performance characteristics of this library?
A: The library is optimized to perform well when using PostgreSQL. The performance of this library is tied to your database, so make sure your server is appropriately configured. We have plans to provide benchmarks in the future.
Please check the Github issues page to see if the issue is already reported. If not, please create a new issue describing the problem with all the necessary details to reproduce it.