postgres-cache
Postgres Cache is a single purpose library to cover a need of a distributed cache and not willing to use Redis/Valkey/Memcached or other external caching systems.
Idea of the library is to store persisted cache in Postgres, and utilize couple of specific optimizations to make it behave comparable with other caching solutions. Local in-memory cache with invalidation via LISTEN/NOTIFY are among those optimizations.
Features
-
Pure Postgres backend – no bespoke services, just a single table plus triggers and LISTEN/NOTIFY for invalidations.
-
TTL + forced invalidation – each entry stores an optional
expires_at, and clients can delete rows explicitly. -
Dogpile protection –
get_or_setuses PostgreSQL advisory locks so only one client recomputes missing items. -
Local in-memory cache – every client keeps a bounded TTL cache that is updated/evicted via database notifications.
-
Configurable Postgres objects –
notify_channelcontrols the LISTEN/NOTIFY channel, andschema_prefixnamespaces every table/function created by the library. -
Optional notifications – set
disable_notiffy=Trueto skip LISTEN/NOTIFY when Postgres connection budgets are tight. -
Load harness – runnable script that spins up many clients to assert read consistency and provide latency stats.
Usage
Install the library from PyPI:
pip install postgres-cache
PostgreSQL-backed cache
import asyncio
from postgres_cache import CacheSettings, PostgresCache
async def main():
dsn = "postgresql://cache_user:cache_pass@localhost:5432/cache_proto"
settings = CacheSettings(
dsn=dsn,
notify_channel="cache_events_marketing",
schema_prefix="marketing_",
)
await PostgresCache.init_db(settings)
async with PostgresCache(settings) as cache:
await cache.set("profile:123", {"name": "Ava"}, ttl_seconds=300)
user = await cache.get_or_set(
"profile:456",
loader=lambda: {"name": "Nova"},
ttl_seconds=120,
)
print(user)
asyncio.run(main())
The clients automatically:
- Maintain a bounded local cache.
- Listen on
notify_channelso updates/deletes on any node evict stale entries everywhere. - Use advisory locks on
get_or_setto avoid thundering herds.
Null cache
Need a drop-in implementation that always hits the loader (for local dev or tests)?
from postgres_cache import NullCache
async with NullCache() as cache:
await cache.set("noop", "value") # does nothing
assert await cache.get("noop") is None
Development setup
Python 3.11+ and uv are required for local development.
make tests– run the pytest suite (requires Postgres running viadocker compose up).make lint-and-format– format & lint codemake harness-load-test– launch the load harness against a local Postgres.make examples-basic-usage/make examples-fastapi-api-cache– run example scripts.
Load testing
See harness/README.md for the load-test instructions and make harness-load-test helper.
Benchmarking
See benchmarks/README.md for installation steps, CLI flags, and instructions for adding more backends to the report. Note that these numbers come from an intentionally narrow, unrealistic benchmark that ignores network latency to focus purely on cache/DB interactions on the same host.
Benchmark summary
| backend | write mean (ms) | write p95 (ms) | write ops/s | read mean (ms) | read p95 (ms) | read ops/s | hit rate |
|---|---|---|---|---|---|---|---|
| postgres-cache | 12.887 | 29.943 | 1023.4 | 1.937 | 5.099 | 10071.9 | 95.9% |
| postgres-no-local-cache | 4.290 | 8.626 | 2284.4 | 2.274 | 3.600 | 9364.5 | 97.9% |
| postgres-no-notify | 1.458 | 2.958 | 3865.2 | 0.208 | 1.624 | 23652.9 | 98.4% |
| valkey | 0.502 | 0.691 | 4804.9 | 0.468 | 0.683 | 18786.0 | 99.1% |
postgres-no-local-cache disables the client-side cache (local_max_entries=0), so the benchmark issues direct Postgres reads without invalidating values pulled from the backend.
postgres-no-notify turns off LISTEN/NOTIFY fan-out (disable_notiffy=True), which means no backend invalidations occur and only the local TTL policy expires entries.
Interpretation: "optimizations" implemented in this libray, does not provide any advantage.
License
Released under the MIT License.
Metadata
Release files for postgres-cache 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| postgres_cache-0.1.1.tar.gz | 16.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| postgres_cache-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.3 kB
Release files / postgres_cache-0.1.1.tar.gz
| Download URL | postgres_cache-0.1.1.tar.gz |
|---|---|
| Size | 16.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c03393c97cc4efade71ae2da987529c65378ddc8d76b5a983c6fdb8ba5139d69
|
|
BLAKE2b-256 checksum How to use checksums |
9ce8420fae9b215e4a5293c474fdf7a29e549594e3a3d79294182511e6324766
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 16, 2025.
Transparency logRelease files / postgres_cache-0.1.1-py3-none-any.whl
| Download URL | postgres_cache-0.1.1-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ee50d6589d523fd849dab9623d6b72701ae2446b81c540b1bd61b49f1fdc3b17
|
|
BLAKE2b-256 checksum How to use checksums |
4d72cdea20ca22b07e475032192f9af9cc647e9b8adaee8a4b34c9baa2d8a79d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 16, 2025.
Transparency logSecurity for postgres-cache 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for postgres_cache-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 16, 2025.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.