coodie

The modern Pydantic-based ODM for Cassandra & ScyllaDB

Define your data models as Python classes, and coodie handles schema synchronization, serialization, and query building β€” with both sync and async APIs.

✨ Feature Highlights

🧬 Pydantic v2 Models β€” full type-checking & validation
⚑ Sync & Async β€” coodie.sync for blocking, coodie.aio for asyncio
πŸ”— Chainable QuerySet β€” .filter() Β· .limit() Β· .order_by()

πŸ”„ Automatic Schema Sync β€” sync_table() creates & evolves tables
πŸ—οΈ Batch & LWT β€” BatchQuery + if_not_exists() support
🎯 Multi-Driver β€” scylla-driver Β· cassandra-driver Β· acsylla

πŸ“¦ Installation

pip install coodie

Choose a driver extra for your cluster:

pip install "coodie[scylla]"      # ScyllaDB / Cassandra (recommended)
pip install "coodie[cassandra]"   # Cassandra via cassandra-driver
pip install "coodie[acsylla]"     # Async-native via acsylla

πŸš€ Quick Start

1. Start a local ScyllaDB (or use an existing cluster):

docker run --name scylla -d -p 9042:9042 scylladb/scylla --smp 1

# Wait for it to be ready (~30s), then create a keyspace
docker exec -it scylla cqlsh -e \
  "CREATE KEYSPACE IF NOT EXISTS my_ks
   WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};"

2. Install coodie:

pip install "coodie[scylla]"

3. Write your first script:

from coodie.sync import Document, init_coodie
from coodie.fields import PrimaryKey
from pydantic import Field
from typing import Annotated
from uuid import UUID, uuid4

# Connect
init_coodie(hosts=["127.0.0.1"], keyspace="my_ks")

# Define a model
class User(Document):
    id: Annotated[UUID, PrimaryKey()] = Field(default_factory=uuid4)
    name: str
    email: str

    class Settings:
        name = "users"

# Sync schema & insert
User.sync_table()
user = User(name="Alice", email="[email protected]")
user.save()

# Query
print(User.find(name="Alice").allow_filtering().all())

πŸ’‘ Async? Just swap coodie.sync for coodie.aio and add await β€” that’s it!

πŸ” How Does coodie Compare?

Feature

coodie

beanie

cqlengine

Database

Cassandra / ScyllaDB

MongoDB

Cassandra

Schema Definition

Pydantic v2 BaseModel

Pydantic v2 BaseModel

Custom columns.* classes

Type Hints

βœ… Native Annotated[]

βœ… Native Pydantic

❌ No type hints

Async Support

βœ… First-class

βœ… First-class

❌ Sync only

Sync Support

βœ… coodie.sync

❌ Async only

βœ… Sync only

Query API

Chainable QuerySet

Chainable FindMany

Chainable QuerySet

Schema Migration

βœ… sync_table()

❌ Manual

βœ… sync_table()

LWT (Compare-and-Set)

βœ… if_not_exists()

N/A

βœ… iff()

Batch Operations

βœ… BatchQuery

❌

βœ… BatchQuery

Counter Columns

βœ… Counter()

❌

βœ… columns.Counter

User-Defined Types

βœ… UserType

❌

βœ… UserType

TTL Support

βœ… Per-save TTL

❌

βœ… Per-save TTL

Pagination

βœ… Token-based PagedResult

βœ… Cursor-based

❌ Manual

Multiple Drivers

βœ… 3 drivers

motor only

cassandra-driver only

Polymorphic Models

βœ… Discriminator

❌

❌

Python Version

3.10+

3.8+

3.6+