Skip to content

Introduction

Popoto is an ORM for Redis and Valkey databases. The familiar syntax makes it easy to use for Django and Flask developers.

Redis and Valkey are storage systems that operate in RAM memory. Since they work at RAM memory level, reading/writing is typically 10-20x faster compared to PostgreSQL and other traditional relational databases.

Valkey Support

Popoto fully supports Valkey, the open-source Redis fork. Simply point your REDIS_URL at a Valkey server - no code changes needed.

Simple Example

Here's a complete example showing how to define a model, create an instance, and retrieve it.

from popoto import Model, KeyField, Field, SortedField, GeoField

class Restaurant(Model):
    name = KeyField()
    cuisine = Field(type=str)
    rating = SortedField(type=float)
    location = GeoField()

Restaurant.create(
    name="Burger Palace",
    cuisine="American",
    rating=4.5,
    location=(40.7128, -74.0060)
)

restaurant = Restaurant.query.get(name="Burger Palace")

print(f"{restaurant.name} serves {restaurant.cuisine} food.")
# => 'Burger Palace serves American food.'

Features

Popoto provides a fast, familiar interface for working with Redis and Valkey.

  • Full Redis and Valkey support - works with both out of the box
  • very fast stores and queries
  • familiar syntax, similar to Django models
  • Async operations for asyncio-based applications
  • Multi-tenancy support via KeyField namespacing
  • Geometric distance search
  • Timeseries for streaming data
  • compatible with Pandas, Xarray for N-dimensional matrix search
  • PubSub for message queues, streaming data processing
  • Agent Memory — programmable memory primitives for AI agents (decay, confidence, associations)
  • Content and Embedding Fields — large content storage, vector embeddings, and semantic search
  • PolicyCache Recipe — reference recipe composing all memory primitives into an RL-style action selection cache
  • SubconsciousMemory Recipe — automatic memory injection and extraction around LLM turns
  • RAG Chatbot Recipe — build a retrieval-augmented chatbot using ContentField, EmbeddingField, and semantic_search

Popoto is ideal for streaming data. The pub/sub module allows you to trigger state updates in real time. Currently being used in production for:

  • trigger buy/sell actions from streaming price data
  • robots sending each other messages for teamwork
  • compressing sensor data and training neural networks

Getting Started

Install

Install Popoto using pip.

pip install popoto

see Popoto on PyPi

Set REDIS_URL in your deployed environment. This is optional on local development.

REDIS_URL = "redis://HOST[:PORT]/DATABASE[?password=PASSWORD]"

See Configuration for full connection options.

Enable Error Reporting (Optional)

Help improve Popoto by opting in to anonymous error reporting. When enabled, library-specific exceptions are sent to the Popoto maintainers via Sentry. This uses an isolated client that never interferes with your own Sentry setup.

import popoto

popoto.enable_error_reporting()

Install with pip install popoto[monitoring] to include the sentry-sdk dependency, or skip this step entirely — Popoto works the same either way.

Define a Model

Start by defining a model class. Models inherit from popoto.Model and define fields for the data you want to store.

from popoto import Model, KeyField, Field, SortedField

class Restaurant(Model):
    name = KeyField()
    cuisine = Field(type=str)
    rating = SortedField(type=float)

See Models and Fields for all Model and Field options, including ContentField for large content storage and EmbeddingField for vector embeddings and semantic search.

See Model Meta Options for configuration like default ordering and TTL.

Create Instances

You can create instances by constructing the model and calling save(), or use the create() shortcut.

restaurant = Restaurant(name="Burger Palace")
restaurant.cuisine = "American"
restaurant.rating = 4.5
restaurant.save()

# single line command
restaurant = Restaurant.create(name="Burger Palace", cuisine="American", rating=4.5)

Retrieve Instances

Use the query interface to retrieve instances by their key fields.

restaurant = Restaurant.query.get(name="Burger Palace")
print(f"{restaurant.name} serves {restaurant.cuisine} food.")
# => 'Burger Palace serves American food.'

See Making Queries for all Query and Filter options.

Delete Instances

Delete an instance by calling its delete() method.

restaurant.delete()

To delete all instances of a model, use delete_all():

# Delete all restaurants and clean up all indexes
Restaurant.delete_all()

# Delete multiple models (delete referencing models first)
for model in [Order, MenuItem, Restaurant]:
    model.delete_all()

Warning

Always use Popoto's delete methods instead of Redis DEL or FLUSHDB. Popoto maintains secondary indexes (sorted sets, geo sets, unique constraints) that must be cleaned up properly. See Bulk Operations for details.

Async Operations

All operations have async counterparts for use in asyncio applications.

import asyncio

async def main():
    restaurant = await Restaurant.async_create(
        name="Burger Palace", cuisine="American", rating=4.5
    )
    loaded = await Restaurant.query.async_get(name="Burger Palace")
    await loaded.async_delete()

asyncio.run(main())

See Async Operations for complete async API documentation and examples.

Popoto supports vector embeddings and semantic search for AI-powered retrieval. Store large content on the filesystem with ContentField, generate embeddings automatically with EmbeddingField, and search by meaning with semantic_search().

import popoto
from popoto import Model, KeyField, ContentField, EmbeddingField
from popoto.embeddings.voyage import VoyageProvider

# Configure once at startup
popoto.configure(
    embedding_provider=VoyageProvider(api_key="your-key"),
)

class Document(Model):
    title = KeyField()
    body = ContentField()
    embedding = EmbeddingField(source="body")

Document.create(title="Q4 Report", body="Revenue exceeded projections by 12%...")

# Search by meaning — returns documents ranked by cosine similarity
results = Document.query.semantic_search("financial performance", limit=5)

Install an embedding provider extra: pip install popoto[voyage] or pip install popoto[openai].

See Content and Embedding Fields for the full guide, and Configuration for setup options.

Popoto gets its name from the Maui dolphin subspecies - the world's smallest dolphin subspecies. Because dolphins are fast moving, agile, and work together in social groups. In the same way, Popoto wraps Redis and Valkey to make it easy to manage streaming timeseries data.

For help building applications with Python/Redis, contact Tom Counsell on LinkedIn.com/in/tomcounsell