A local, SQL-queryable, rebuildable materialized view for Kafka-consuming applications, backed durably by a per-partition Kafka changelog
Project description
KSQLite
Turn SQLite into a distributed, durable store: millisecond-local SQL on every instance, with Kafka holding the data and rehydrating it on demand.
KSQLite gives each instance of your app a fast, local SQLite database of the shards it owns — durable on disk and queryable with plain SQL. Kafka is the distribution and recovery layer: a per-shard changelog carries every write and lives on the network, so a new or replacement instance rehydrates its local SQLite by replaying that changelog. Your data isn't pinned to one box — it follows ownership across the fleet.
KSQLite is an embeddable library, not a service. Use it two ways:
- Attached to a Kafka consumer. You keep your own consumer and hook KSQLite into its rebalance listener; local state follows partition ownership automatically.
- Standalone. No consumer at all. You claim shards yourself and get durable local SQL storage that any instance can rebuild — Kafka is deployed to hold the data, not to feed it.
A shard is one unit of ownership: a single (topic, partition), backed by
one changelog topic. The API spells it TopicPartition. When you consume a
topic, a shard is one of its partitions; when you don't, it's just a name you
chose.
Requirements
- Python >= 3.10
- SQLite >= 3.38 (otherwise, see How to run on an older SQLite)
- A Kafka-compatible broker
Install
uv add ksqlite-py
Quickstart
import asyncio
from aiokafka import TopicPartition
from ksqlite import GeneratedColumn, Index, KSQLite
SHARD = TopicPartition("messages", 0)
async def main() -> None:
async with KSQLite(
db_path="state.db",
bootstrap_servers="localhost:9092",
generated_columns=[GeneratedColumn("thread_id", "$.thread_id")],
indexes=[Index("ix_thread", ["thread_id"])],
create_topics_retention_ms=-1, # dev convenience; ops pre-creates in prod
) as store:
# Claim the shard: creates the changelog if needed, replays it, and
# makes its rows visible. A consumer app calls this from its rebalance
# listener instead.
await store.on_partitions_assigned([SHARD])
await store.append(
source=SHARD,
entity_key="th-42",
payload={"thread_id": "th-42", "text": "hello"},
)
rows = await store.query(
"SELECT payload FROM records WHERE thread_id = ?", ["th-42"]
)
print([row["payload"] for row in rows])
asyncio.run(main())
Delete state.db and run it again — the row from the previous run is still
there, replayed from the changelog before the new append. (You get one more row
each run: append() is append-only, so it inserts rather than overwriting.)
For the same thing at a walking pace, see the tutorial.
Documentation
Tutorial, how-to guides, reference, and explanation live in docs/.
Development
uv sync
uv run pytest # unit + integration (fakes, real SQLite)
uv run pytest -m e2e # real-broker suite (needs Docker)
uv run ruff check && uv run ruff format --check && uv run mypy
The end-to-end suite runs against a pinned Redpanda container
(docker.redpanda.com/redpandadata/redpanda:v24.2.20) and auto-skips when
Docker is unavailable.
License
This project is licensed under the MIT License - see the LICENSE file for details.
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 Distribution
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 ksqlite_py-0.1.1.tar.gz.
File metadata
- Download URL: ksqlite_py-0.1.1.tar.gz
- Upload date:
- Size: 28.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f39a214655c24a881bc82f7dfe624924bb35f414b875c404f6609e884f919f6
|
|
| MD5 |
f7f8168f15d043b58fab0139e5bf051d
|
|
| BLAKE2b-256 |
decb32ac36f08845e2ca2e7173c99135ed843c4c9e46b4121764f7ca5ca29c8d
|
Provenance
The following attestation bundles were made for ksqlite_py-0.1.1.tar.gz:
Publisher:
release.yml on calf-ai/ksqlite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ksqlite_py-0.1.1.tar.gz -
Subject digest:
7f39a214655c24a881bc82f7dfe624924bb35f414b875c404f6609e884f919f6 - Sigstore transparency entry: 2171558819
- Sigstore integration time:
-
Permalink:
calf-ai/ksqlite@345e9b0310a7228427cbc8014dc792696e48f6cb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/calf-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@345e9b0310a7228427cbc8014dc792696e48f6cb -
Trigger Event:
push
-
Statement type:
File details
Details for the file ksqlite_py-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ksqlite_py-0.1.1-py3-none-any.whl
- Upload date:
- Size: 34.9 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 |
de7523d821bec2f465b350065168cc5172e3d0ddd60a5bc06d48ca7144b88226
|
|
| MD5 |
906c24f3d49d3a53eafd5d94aa57aca4
|
|
| BLAKE2b-256 |
53805283f99aa093d5cdc4d963a7d4746100a7a73198528a35b2f8fa98553d69
|
Provenance
The following attestation bundles were made for ksqlite_py-0.1.1-py3-none-any.whl:
Publisher:
release.yml on calf-ai/ksqlite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ksqlite_py-0.1.1-py3-none-any.whl -
Subject digest:
de7523d821bec2f465b350065168cc5172e3d0ddd60a5bc06d48ca7144b88226 - Sigstore transparency entry: 2171558823
- Sigstore integration time:
-
Permalink:
calf-ai/ksqlite@345e9b0310a7228427cbc8014dc792696e48f6cb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/calf-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@345e9b0310a7228427cbc8014dc792696e48f6cb -
Trigger Event:
push
-
Statement type: