Skip to content

Protean

Pragmatic Framework for Ambitious Applications

Python Release Build Status Coverage

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
  1. Domain — The central registry that wires all elements together.
  2. Aggregate — The core building block encapsulating fields and business logic.
  3. Raising an Eventraise_() emits a domain event to notify the rest of the system.
  4. Event — An immutable record of something that happened in the domain.
  5. Command — An intent to change state, carrying just the needed data.
  6. Command Handler — Receives a command, creates/updates aggregates, and persists them.
  7. 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.

    DDD Pathway

  • CQRS


    Separate reads from writes with commands, command handlers, and read-optimized projections.

    CQRS Pathway

  • Event Sourcing


    Derive state from event replay. Full audit trail, temporal queries, and complete traceability.

    Event Sourcing Pathway

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.

Full Quality Report


Explore the Documentation

  • Quickstart


    Build a domain in 5 minutes — no infrastructure required.

    Quickstart

  • Tutorial


    15-part guide from your first aggregate to production.

    Tutorial

  • Guides


    Deep reference for every concept, pattern, and technique.

    Guides

  • Core Concepts


    DDD, CQRS, and Event Sourcing explained.

    Core Concepts

  • Adapters


    PostgreSQL, Redis, Elasticsearch, MessageDB, and more.

    Adapters

  • Patterns & Recipes


    Battle-tested solutions for common challenges.

    Patterns

  • How Do I...?


    Find the right guide by what you're trying to accomplish.

    How Do I...?