Skip to main content

🐾 PURR

The Zero-Infrastructure SQLite-backed alternative to Redis.

State Machine, Sagas, Event Streams, and Key-Value Store with SQLite WAL persistence.

CI Python 3.11+ License: MIT


💡 Why PURR?

Modern applications and autonomous AI agents need reliable state management, event streaming, and transactional guarantees. Typically, this forces you to deploy and manage a heavy infrastructure stack: Redis, Redis Streams, Celery, and RabbitMQ.

PURR replaces that complexity with a single embedded SQLite database file.

  • 🪶 Zero Infrastructure: Pure Python. No Docker containers, no external services, no background daemons, zero network overhead.
  • ⚡ SQLite WAL Mode: Concurrency-safe, high-throughput atomic read/writes that survive crashes and power loss.
  • 🔄 3-in-1 Architecture:
    1. Key-Value Store: Fast storage with TTL auto-expiry, atomic multi-set, and numeric operations.
    2. State Machine & Sagas: FSM engine with persistent snapshots, guards, and automatic rollback on step failure (compensating transactions).
    3. Event Streams & Pub/Sub: Redis Streams-like append-only event store with consumer cursors and middleware pipelines (rate limiting, deduplication, filtering).

📦 Installation

pip install py-purr

The distribution is called py-purr, but you import it as purr:

from purr import Store

The name purr on PyPI belongs to an unrelated package, so pip install purr would have installed somebody else's library. This is the only reason the distribution and the import differ.

(Or install locally via pip install -e .)


🚀 Quick Tour

1. Key-Value Store with TTL & Atomic Operations

from purr import Store

# Initialize store (in-memory or persistent file)
store = Store("app_state.db")

# Basic KV operations
store.set("user:1001", {"name": "Alice", "role": "admin"})
user = store.get("user:1001")

# Auto-expiring keys (TTL in seconds)
store.set("session_token", "xyz-123", ttl=3600)

# Atomic multi-set and counters
store.mset({"counter": 0, "status": "active"})
store.incr("counter", 1)  # returns 1

2. State Machine with Persistence & Snapshots

from purr import StateMachine

sm = StateMachine("order_pipeline", db_path="pipeline.db")

# Define transitions
sm.add_transition("idle", "processing", "start_job")
sm.add_transition("processing", "completed", "finish_job")
sm.add_transition("processing", "failed", "report_error")

# Transition state (machine starts empty — set the initial state first)
sm.set_state("idle")
sm.send("start_job")
assert sm.current_state == "processing"

# Take persistent snapshots for crash recovery
sm.snapshot()
sm.restore_snapshot()

3. Sagas (Compensating Transactions)

Execute multi-step distributed operations safely. If any step fails, PURR automatically executes compensating rollback actions in reverse order.

import asyncio
from purr import Saga

saga = Saga("deploy_workflow")

async def allocate_resources(ctx):
    ctx["allocated"] = True
    return ctx

async def release_resources(ctx):
    ctx["allocated"] = False

async def run_failing_migration(ctx):
    raise RuntimeError("Migration failed!")

# Define steps: (name, forward_action, compensation)
saga.add_step("reserve", allocate_resources, compensation=release_resources)
saga.add_step("migrate", run_failing_migration)

# If step 2 fails, 'release_resources' is executed automatically,
# then the error propagates (no result flag — expect the raise)
try:
    asyncio.run(saga.execute())
except RuntimeError as exc:
    assert str(exc) == "Migration failed!"

4. Event Streams & Consumer Groups (Redis Streams alternative)

Append-only persistent event logs with cursor tracking across multiple consumers.

from purr import Event, EventStream, EventType

stream = EventStream("events.db")

# Publish events
stream.append(Event(type=EventType.SYSTEM, topic="user_signups", payload={"user_id": 42}))

# Read events, track consumer cursor
events, last_id = stream.read(topic="user_signups", limit=50)
stream.set_cursor("my-consumer", last_id)

5. Pub/Sub with Middleware Pipeline

import asyncio
from purr import Event, EventBus, EventType
from purr.middleware import DedupMiddleware, MiddlewarePipeline, RateLimitMiddleware

bus = EventBus()

# Middleware runs through a separate pipeline (bus has no .use());
# exact-topic match plus the "*" wildcard only
pipeline = MiddlewarePipeline()
pipeline.add(DedupMiddleware(ttl_seconds=60))
pipeline.add(RateLimitMiddleware(max_per_second=100))

async def handle_alert(event):
    print(f"Alert received: {event.payload}")

bus.subscribe("system.alerts.cpu", handle_alert)
event = Event(type=EventType.SYSTEM, topic="system.alerts.cpu", payload={"usage": "98%"})
asyncio.run(bus.publish(event))
# Same event through the middleware pipeline (dedup + rate limit), then to the handler
asyncio.run(pipeline.execute(event, handle_alert))

🛠️ Development & Testing

uv sync --extra dev
uv run pytest -v

The suite is 95 tests and runs in under a second. CI additionally enforces ruff check, ruff format --check, and a coverage gate of 85% on Python 3.11, 3.12 and 3.13.


📄 License

MIT License. See LICENSE for details.

Metadata

Release files for py-purr 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-purr 0.1.0
File Size Uploaded
py_purr-0.1.0.tar.gz 47.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-purr 0.1.0
File Interpreter ABI Platform
py_purr-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 68.9 kB

Release files / py_purr-0.1.0.tar.gz

Download URL py_purr-0.1.0.tar.gz
Size 47.2 kB
Tags Source
SHA-256 checksum
How to use checksums
65d57b894b518e769a92dcfe74cebd7773a63ff0108e99933a53141c35053211
BLAKE2b-256 checksum
How to use checksums
2b29c6a609e72f5f2e0966e4e56b398c383d051d1aada3048c004eac58947610
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 7, 2026.

Transparency log

Release files / py_purr-0.1.0-py3-none-any.whl

Download URL py_purr-0.1.0-py3-none-any.whl
Size 21.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5f617460b72e9138b0c49d3c5d3598e84b64b4b6581a7ec35f9e28834966f24
BLAKE2b-256 checksum
How to use checksums
24af156d24092642b0e98e79a84eca975692085688cf19abc320b81fa47adafa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page