Build a Python Application with Cassandra

Build a simple user management application using the Apache Cassandra Python driver. This quickstart takes about 10 minutes to complete.

What You’ll Build

A Python script that connects to Cassandra, creates a keyspace and table, inserts records using prepared statements, queries them back, and performs an update and delete. You will have a working end-to-end example you can adapt for your own application.

Prerequisites

  • Python 3.8 or later

  • pip

  • Docker (for running a local Cassandra node)

Start Cassandra

Start a single-node Cassandra cluster using Docker:

docker pull cassandra:latest
docker run --name cassandra -d -p 9042:9042 cassandra:latest

Wait 30-60 seconds for the node to initialize, then verify readiness:

docker exec cassandra cqlsh -e "DESCRIBE KEYSPACES"

Repeat the command until it returns a list of system keyspaces without an error.

The Python driver handles connection pooling automatically. You do not need to manage individual connections or threads.

Install the Driver

Install the Apache Cassandra Python driver from PyPI:

pip install cassandra-driver

Connect to Cassandra

Create a file named app.py and add the following connection code:

from cassandra.cluster import Cluster

cluster = Cluster(['127.0.0.1'])
session = cluster.connect()
print("Connected to Cassandra!")

Run it to verify connectivity:

python app.py

You should see Connected to Cassandra! printed to the console.

Create a Keyspace and Table

Add the keyspace and table setup to app.py:

session.execute("""
    CREATE KEYSPACE IF NOT EXISTS quickstart
    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}
""")
session.set_keyspace('quickstart')

session.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id UUID PRIMARY KEY,
        name text,
        email text
    )
""")
print("Keyspace and table ready.")

SimpleStrategy with a replication factor of 1 is appropriate for local development. Use NetworkTopologyStrategy in production clusters. The examples use random UUIDs because the row ID is only a lookup key for later updates and deletes.

Insert Data

Use prepared statements when executing the same query multiple times. They are compiled once by the cluster and cached for subsequent calls.

import uuid

insert_stmt = session.prepare(
    "INSERT INTO users (id, name, email) VALUES (%s, %s, %s)"
)

session.execute(insert_stmt, [uuid.uuid4(), "Alice", "alice@example.com"])
session.execute(insert_stmt, [uuid.uuid4(), "Bob", "bob@example.com"])
print("Inserted 2 users.")
Use prepared statements for repeated queries — they’re faster and safer. The driver handles parameter binding and protects against injection.

Query Data

Fetch all rows and iterate over the result set:

rows = session.execute("SELECT * FROM users")
for row in rows:
    print(f"User: {row.name} ({row.email})")

The result set is iterable. For large tables, the driver automatically pages through results in batches to avoid loading everything into memory at once.

Update and Delete

To update or delete a specific row you need the row’s UUID. Store it when inserting:

alice_id = uuid.uuid4()
session.execute(insert_stmt, [alice_id, "Alice", "alice@example.com"])

# Update Alice's email address
session.execute(
    "UPDATE users SET email = %s WHERE id = %s",
    ["alice@newdomain.com", alice_id]
)
print("Updated Alice's email.")

# Delete Alice's record
session.execute(
    "DELETE FROM users WHERE id = %s",
    [alice_id]
)
print("Deleted Alice's record.")

Complete Script

Here is the full app.py combining all of the above steps, with proper cleanup at the end:

import uuid
from cassandra.cluster import Cluster

# Connect
cluster = Cluster(['127.0.0.1'])
session = cluster.connect()
print("Connected to Cassandra!")

# Keyspace and table
session.execute("""
    CREATE KEYSPACE IF NOT EXISTS quickstart
    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}
""")
session.set_keyspace('quickstart')
session.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id UUID PRIMARY KEY,
        name text,
        email text
    )
""")
print("Keyspace and table ready.")

# Insert using a prepared statement
insert_stmt = session.prepare(
    "INSERT INTO users (id, name, email) VALUES (%s, %s, %s)"
)
alice_id = uuid.uuid4()
bob_id = uuid.uuid4()
session.execute(insert_stmt, [alice_id, "Alice", "alice@example.com"])
session.execute(insert_stmt, [bob_id, "Bob", "bob@example.com"])
print("Inserted 2 users.")

# Query
rows = session.execute("SELECT * FROM users")
for row in rows:
    print(f"User: {row.name} ({row.email})")

# Update
session.execute(
    "UPDATE users SET email = %s WHERE id = %s",
    ["alice@newdomain.com", alice_id]
)
print("Updated Alice's email.")

# Delete
session.execute("DELETE FROM users WHERE id = %s", [alice_id])
print("Deleted Alice's record.")

# Clean up
cluster.shutdown()
print("Done.")

Run the complete script:

python app.py

Expected output:

Connected to Cassandra!
Keyspace and table ready.
Inserted 2 users.
User: Alice (alice@example.com)
User: Bob (bob@example.com)
Updated Alice's email.
Deleted Alice's record.
Done.
This quickstart also works with Cassandra 6. When you are ready to go beyond basic CRUD, see ACID Transactions for BEGIN TRANSACTION and Constraints for schema validation.

What’s Next

  • Data Modeling — design tables for your access patterns before writing application code

  • ACID Transactions — use lightweight transactions and multi-partition transactions in Cassandra 6

  • Choose a Driver — compare Python, Java, Go, and other driver options

  • Vector Search — build AI-powered search with vector embeddings