Fast in-memory DataFrame cache using DuckDB with SQL query interface
Project description
cached_duckdb
Fast in-memory DataFrame cache using DuckDB with SQL query interface.
Overview
cached_duckdb replaces pandas dict-based caching with DuckDB in-memory connections for:
- Columnar storage - 20-30% less RAM than pandas
- SQL queries - Single-pass filter+aggregate operations
- Concurrency - Safe parallel reads during writes
- Zero disk usage - Pure in-memory like pandas
Key Features
- Generic database/table API - Works with any cache-based system
- Two storage modes:
single_db: One connection per database (enables cross-table JOINs)per_table_db: One connection per (database, table) pair (fully parallel writes)
- Atomic swap - Readers see 100% old or 100% new data, never partial
- TTL-based expiry - Background cleanup with lazy stale flagging
- Scheduler-managed tables - Bypass TTL for scheduled updates
- Thread-safe operations - Per-database or per-table locking
Installation
From PyPI (Recommended)
pip install cached-duckdb
Install Specific Version
pip install cached-duckdb==0.2.0
With Optional Protected Build Extras
pip install "cached-duckdb[all]"
From Local Source
pip install -r requirements.txt
Or install in development mode:
pip install -e .
Verify installed version:
import cached_duckdb
print(cached_duckdb.__version__)
Quick Start
Basic Usage
from cached_duckdb import DuckDbCacheManager
import pandas as pd
# Initialize cache (singleton)
cache = DuckDbCacheManager()
# Store DataFrame
df = pd.DataFrame({
'date': ['2026-01-01', '2026-01-02'],
'amount': [1000, 2000],
'country': ['USA', 'UK']
})
cache.store(database="client_abc", table="sales_data", df=df)
# Query with SQL filtering
result = cache.query(
database="client_abc",
table="sales_data",
sql_where="amount > 1000 AND country = 'USA'",
columns=["date", "amount"]
)
print(result)
Advanced Queries
# Get all data
df = cache.query(database="app_x", table="dataset_1")
# Filter with WHERE
df = cache.query(
database="app_x",
table="dataset_1",
sql_where="age > 25 AND country = 'USA'"
)
# Select specific columns
df = cache.query(
database="app_x",
table="dataset_1",
columns=["name", "age", "salary"]
)
# Limit results
df = cache.query(
database="app_x",
table="dataset_1",
sql_where="date >= '2026-01-01'",
limit=100
)
Cross-Table JOINs (single_db mode)
# Execute raw SQL for complex queries
sql = """
SELECT s.date, s.amount, o.customer_name
FROM sales_data s
JOIN orders o ON s.order_id = o.id
WHERE s.amount > 1000
"""
result = cache.execute_sql(database="client_abc", sql=sql)
Check if Data Exists
if cache.exists(database="client_abc", table="sales_data"):
# Data is ready and fresh
df = cache.query(database="client_abc", table="sales_data")
else:
# Data missing or stale - reload needed
df = load_from_source()
cache.store(database="client_abc", table="sales_data", df=df)
TTL and Scheduler-Managed Tables
# Store with custom TTL
cache.store(
database="client_abc",
table="sales_data",
df=df,
ttl_minutes=60 # Expires after 60 minutes
)
# Scheduler-managed table (no auto-expiry on reads)
cache.store(
database="client_abc",
table="sales_data",
df=df,
scheduler_managed=True # Only scheduler updates it
)
Invalidate Cache
# Invalidate one table
cache.invalidate(database="client_abc", table="sales_data")
# Invalidate all tables for a database
cache.invalidate(database="client_abc")
Get Metadata
# Last updated timestamp
last_updated = cache.get_last_updated(database="client_abc", table="sales_data")
print(f"Last updated: {last_updated}")
# Table info
info = cache.get_table_info(database="client_abc", table="sales_data")
print(f"Rows: {info['row_count']}")
print(f"Columns: {info['columns']}")
print(f"Types: {info['column_types']}")
Documentation
Author
sreeyenan (sreeyenanek@gmail.com)
Version
Current version: 0.2.0
Configuration
Environment Variables
# Storage mode: single_db or per_table_db
CACHED_DUCKDB_DEFAULT_MODE=single_db
# Default TTL in minutes
CACHED_DUCKDB_DEFAULT_TTL_MINUTES=30
# Cleanup thread interval
CACHED_DUCKDB_CLEANUP_INTERVAL_MINUTES=5
# Lock timeout in seconds
CACHED_DUCKDB_LOCK_TIMEOUT_SECONDS=30
# Path to connector config file (optional)
CACHED_DUCKDB_CONFIG_FILE_PATH=/path/to/connector_config.json
# Logger name
CACHED_DUCKDB_LOG_NAME=cached_duckdb
Per-Database Configuration File
Create connector_config.json for per-database settings:
{
"client_abc": {
"duck_cache_mode": "per_table_db",
"default_cache_ttl_minutes": 45,
"sales_data": {
"cache_ttl_minutes": 60,
"scheduler_managed": false
},
"live_feed": {
"cache_ttl_minutes": 0,
"scheduler_managed": true
}
},
"client_xyz": {
"duck_cache_mode": "single_db"
}
}
Priority order:
- Per-table config in JSON file (highest)
- Per-database config in JSON file
- Environment variables
- Hardcoded defaults (lowest)
Load Configuration
from cached_duckdb import DuckDbCacheConfig, DuckDbCacheManager
# From environment
config = DuckDbCacheConfig.from_env()
cache = DuckDbCacheManager(config)
# From dict
config = DuckDbCacheConfig.from_dict({
"default_mode": "single_db",
"default_cache_ttl_minutes": 30,
"config_file_path": "/path/to/connector_config.json"
})
cache = DuckDbCacheManager(config)
Storage Modes
Mode A: single_db (Default)
- One DuckDB connection per
database - Multiple tables share the same connection
- Enables cross-table SQL JOINs
- Write contention: One lock per database
Use when: Database has few tables (< 20) or need cross-table queries
Mode B: per_table_db
- One DuckDB connection per
(database, table)pair - Each table is fully isolated
- Zero write contention between tables
- Fully parallel writes
Use when: Database has many tables (20+) or high write concurrency
Architecture
DuckDbCacheManager (singleton)
├── CacheStore - Atomic writes, table management
├── CacheQuery - SQL queries, metadata
├── TTLRegistry - TTL tracking, cleanup thread
└── CacheConfigResolver - Per-database config resolution
Thread Safety
- store(): Write-locked per database or per table
- query(): Lock-free parallel reads
- invalidate(): Write-locked, waits for active readers
- Background cleanup: Minimal locking, uses stale flags
Use Cases
- Multi-tenant web APIs - Cache per tenant with
database=tenant_id - Analytics dashboards - Fast in-memory OLAP queries
- ETL pipelines - Store intermediate DataFrames
- Session managers - Replace pandas dict caching
- Microservices - Shared cache library across services
API Reference
DuckDbCacheManager
store(database, table, df, ttl_minutes=None, scheduler_managed=False)- Store DataFramequery(database, table, sql_where=None, columns=None, limit=None)- Query with filteringexecute_sql(database, sql)- Execute raw SQLexists(database, table)- Check if exists and freshinvalidate(database, table=None)- Remove from cacheget_last_updated(database, table)- Get timestampget_table_info(database, table)- Get metadataget_raw_connection(database, table=None)- Get DuckDB connectionshutdown()- Close all connections
Exceptions
DuckDbCacheError- Base exceptionDuckDbCacheConfigError- Configuration errorDuckDbCacheLockError- Lock acquisition failedDuckDbCacheNotFoundError- Table not foundDuckDbCacheStaleError- Data is stale
License
MIT License - see LICENSE file
Author
sreeyenan
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cached_duckdb-0.2.0.tar.gz.
File metadata
- Download URL: cached_duckdb-0.2.0.tar.gz
- Upload date:
- Size: 45.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a75cbae8356c82630e0c17d80f5b4addff0b4c18c0528b1f404830f9c6bc1bf7
|
|
| MD5 |
fd42e84234c8006ba04ed56b353b6fff
|
|
| BLAKE2b-256 |
d67046a69ac79113869344f68ab345e7012d4a5ee3211b210b61e9cbfbeb0518
|
Provenance
The following attestation bundles were made for cached_duckdb-0.2.0.tar.gz:
Publisher:
publish.yml on sreeyenan/cached_duckdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cached_duckdb-0.2.0.tar.gz -
Subject digest:
a75cbae8356c82630e0c17d80f5b4addff0b4c18c0528b1f404830f9c6bc1bf7 - Sigstore transparency entry: 1694208824
- Sigstore integration time:
-
Permalink:
sreeyenan/cached_duckdb@3e6f6cc748e3415968c2bf939d1a56b367685290 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sreeyenan
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3e6f6cc748e3415968c2bf939d1a56b367685290 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cached_duckdb-0.2.0-py3-none-any.whl.
File metadata
- Download URL: cached_duckdb-0.2.0-py3-none-any.whl
- Upload date:
- Size: 51.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fbe57e2fc5b0099d09b4b492157115ca4f2c59b54a8ad35eda6cf8a8f9f2820
|
|
| MD5 |
5dfb9d31aac2dc4def607f894e70da41
|
|
| BLAKE2b-256 |
75ff3343b4f8a289debf49852f32d330e47e4eb006d85e1ae3e1d340dc1b82e1
|
Provenance
The following attestation bundles were made for cached_duckdb-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on sreeyenan/cached_duckdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cached_duckdb-0.2.0-py3-none-any.whl -
Subject digest:
0fbe57e2fc5b0099d09b4b492157115ca4f2c59b54a8ad35eda6cf8a8f9f2820 - Sigstore transparency entry: 1694208924
- Sigstore integration time:
-
Permalink:
sreeyenan/cached_duckdb@3e6f6cc748e3415968c2bf939d1a56b367685290 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sreeyenan
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3e6f6cc748e3415968c2bf939d1a56b367685290 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cached_duckdb-0.2.0-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: cached_duckdb-0.2.0-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 379.2 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bbc21540dd5890da5762ac1585e1f753f14196febb75690733b3d448abbee8e
|
|
| MD5 |
3f0c702973fc858aa4e9d570fb245f69
|
|
| BLAKE2b-256 |
341a24cf26d0ba648a23256444c2c739b506260c8dfe0e9d388a97a34f9ac6c2
|
Provenance
The following attestation bundles were made for cached_duckdb-0.2.0-cp311-cp311-win_amd64.whl:
Publisher:
publish.yml on sreeyenan/cached_duckdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cached_duckdb-0.2.0-cp311-cp311-win_amd64.whl -
Subject digest:
8bbc21540dd5890da5762ac1585e1f753f14196febb75690733b3d448abbee8e - Sigstore transparency entry: 1694335774
- Sigstore integration time:
-
Permalink:
sreeyenan/cached_duckdb@fde300bd59232dc9c6a6499c949090a70c6183da -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sreeyenan
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fde300bd59232dc9c6a6499c949090a70c6183da -
Trigger Event:
push
-
Statement type:
File details
Details for the file cached_duckdb-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: cached_duckdb-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.6 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
745ca9229bd5b6d83733057030ceb9293c1ea17129fa3993a4d4da49d9533f7d
|
|
| MD5 |
4da9678e38fbc40a12c76a0ac4a2d415
|
|
| BLAKE2b-256 |
c74ecfc48be49f0b226d70ceddc043de294b380fdf058edceb1a0042a65554cb
|
Provenance
The following attestation bundles were made for cached_duckdb-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
publish.yml on sreeyenan/cached_duckdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cached_duckdb-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
745ca9229bd5b6d83733057030ceb9293c1ea17129fa3993a4d4da49d9533f7d - Sigstore transparency entry: 1694335214
- Sigstore integration time:
-
Permalink:
sreeyenan/cached_duckdb@fde300bd59232dc9c6a6499c949090a70c6183da -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sreeyenan
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fde300bd59232dc9c6a6499c949090a70c6183da -
Trigger Event:
push
-
Statement type:
File details
Details for the file cached_duckdb-0.2.0-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: cached_duckdb-0.2.0-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 417.8 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03d773aa2d65a54ae85eea39e62c71767cd431325984cc3929a59fbd3f18c085
|
|
| MD5 |
29c8c6c6dc45dbda0e17638c38af54c9
|
|
| BLAKE2b-256 |
061d2a00d6a4bb412bc9e8209f567d7a6f788f88430cac2f6116a5ef0f172e0f
|
Provenance
The following attestation bundles were made for cached_duckdb-0.2.0-cp311-cp311-macosx_11_0_arm64.whl:
Publisher:
publish.yml on sreeyenan/cached_duckdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cached_duckdb-0.2.0-cp311-cp311-macosx_11_0_arm64.whl -
Subject digest:
03d773aa2d65a54ae85eea39e62c71767cd431325984cc3929a59fbd3f18c085 - Sigstore transparency entry: 1694335560
- Sigstore integration time:
-
Permalink:
sreeyenan/cached_duckdb@fde300bd59232dc9c6a6499c949090a70c6183da -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sreeyenan
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fde300bd59232dc9c6a6499c949090a70c6183da -
Trigger Event:
push
-
Statement type:
File details
Details for the file cached_duckdb-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl.
File metadata
- Download URL: cached_duckdb-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl
- Upload date:
- Size: 428.1 kB
- Tags: CPython 3.11, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
101445d9a4cf3781b046184f6cba8a4737fe1a052c23a868a88989ca32c8cbeb
|
|
| MD5 |
c69433fa18c4059cc68fd65887440bae
|
|
| BLAKE2b-256 |
6a89dd1caa6bf4f9feb51835216b75a0d2fc44d2c6c3b2e05a8b9c14d0696a52
|
Provenance
The following attestation bundles were made for cached_duckdb-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl:
Publisher:
publish.yml on sreeyenan/cached_duckdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cached_duckdb-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl -
Subject digest:
101445d9a4cf3781b046184f6cba8a4737fe1a052c23a868a88989ca32c8cbeb - Sigstore transparency entry: 1694335412
- Sigstore integration time:
-
Permalink:
sreeyenan/cached_duckdb@fde300bd59232dc9c6a6499c949090a70c6183da -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sreeyenan
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fde300bd59232dc9c6a6499c949090a70c6183da -
Trigger Event:
push
-
Statement type: