
Pragmatic Framework for Ambitious Applications
Build domain-driven Python applications with clean architecture. Protean gives you DDD, CQRS, and Event Sourcing — with pluggable infrastructure and zero boilerplate.
Get Started Tutorial All Content
See It in Action
from protean import Domain, handle
from protean.fields import Identifier, String, Text
from protean.utils.globals import current_domain
domain = Domain() # (1)!
@domain.aggregate # (2)!
class Post:
title: String(max_length=100, required=True)
body: Text(required=True)
status: String(max_length=20, default="DRAFT")
def publish(self):
self.status = "PUBLISHED"
self.raise_(PostPublished(post_id=self.id, title=self.title)) # (3)!
@domain.event(part_of="Post") # (4)!
class PostPublished:
post_id: Identifier(required=True)
title: String(required=True)
@domain.command(part_of="Post") # (5)!
class CreatePost:
title: String(max_length=100, required=True)
body: Text(required=True)
@domain.command_handler(part_of=Post) # (6)!
class PostCommandHandler:
@handle(CreatePost)
def create_post(self, command: CreatePost):
post = Post(title=command.title, body=command.body)
current_domain.repository_for(Post).add(post) # (7)!
return post.id
- Domain — The central registry that wires all elements together.
- Aggregate — The core building block encapsulating fields and business logic.
- Raising an Event —
raise_()emits a domain event to notify the rest of the system. - Event — An immutable record of something that happened in the domain.
- Command — An intent to change state, carrying just the needed data.
- Command Handler — Receives a command, creates/updates aggregates, and persists them.
- Repository — Built-in persistence abstraction to add, get, or remove aggregates without touching the database directly.
Aggregates, commands, events, and handlers — all in pure Python, with decorators that wire everything together. No infrastructure required to get started.
Why Protean?
-
Domain-First
Model your business in pure Python. No ORM inheritance, no framework lock-in. Your domain code reads like the business, enabling collaboration between developers and domain experts.
-
Plug In Infrastructure Later
Start with in-memory adapters — no database, no broker, no setup. When you're ready, swap in PostgreSQL, Redis, Elasticsearch, or MessageDB through configuration. No code changes.
-
Three Architectural Paths
Begin with DDD, evolve to CQRS, adopt Event Sourcing — all within the same framework. Mix patterns per aggregate. Pragmatism over purity.
-
Test Everything
3,826 tests with a 3.5:1 test-to-code ratio. Run your full domain test suite in-memory in seconds. Every commit is tested against PostgreSQL, Redis, Elasticsearch, MessageDB, and MSSQL across Python 3.11-3.14.
Choose Your Path
Protean supports three architectural approaches. Each builds on the one before it — start simple and add sophistication as your needs evolve.
graph LR
DDD["<strong>Domain-Driven Design</strong><br/>Application Services<br/>Repositories<br/>Events"]
CQRS["<strong>CQRS</strong><br/>Commands & Handlers<br/>Projections<br/>Read/Write Separation"]
ES["<strong>Event Sourcing</strong><br/>Event Replay<br/>Temporal Queries<br/>Full Audit Trail"]
DDD --> CQRS --> ES
style DDD fill:#e8f5e9,stroke:#43a047
style CQRS fill:#e3f2fd,stroke:#1e88e5
style ES fill:#fce4ec,stroke:#e53935
-
Domain-Driven Design
Clean domain modeling with application services, repositories, and event-driven side effects. The simplest way to start.
-
CQRS
Separate reads from writes with commands, command handlers, and read-optimized projections.
-
Event Sourcing
Derive state from event replay. Full audit trail, temporal queries, and complete traceability.
Not sure which to pick? Start with DDD — you can evolve later. See Choose a Path for guidance.
Built to Last
-
3,826 Tests
3.5:1 test-to-code ratio. Every commit validated against PostgreSQL, Redis, Elasticsearch, MessageDB, and MSSQL.
-
Zero Lint Violations
Fully clean Ruff linting and formatting, enforced on every commit via pre-commit hooks.
-
A-Grade Maintainability
97% of source files score in the highest maintainability tier. Average cyclomatic complexity of 2.97.
-
12 Adapters, 5 Ports
Pluggable infrastructure across databases, brokers, event stores, and caches — tested across 4 Python versions.
Explore the Documentation
-
Quickstart
Build a domain in 5 minutes — no infrastructure required.
-
Tutorial
15-part guide from your first aggregate to production.
-
Guides
Deep reference for every concept, pattern, and technique.
-
Core Concepts
DDD, CQRS, and Event Sourcing explained.
-
Adapters
PostgreSQL, Redis, Elasticsearch, MessageDB, and more.
-
Patterns & Recipes
Battle-tested solutions for common challenges.
-
How Do I...?
Find the right guide by what you're trying to accomplish.