Skip to content

Protean

Pragmatic Framework for Ambitious Applications

Python Release Build Status Coverage Tests Maintainability

Build domain-driven Python applications with clean architecture. Start with DDD, evolve to CQRS or Event Sourcing — with pluggable infrastructure and zero boilerplate.

Get Started Tutorial How Do I...?


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.


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.


Choose Your Path

Protean supports three architectural approaches. Each builds on the one before it — start simple and add sophistication as your needs evolve.

Path Best for
Domain-Driven Design Clean domain modeling — the simplest way to start
CQRS Separate reads from writes with commands and projections
Event Sourcing Full audit trail, temporal queries, and event replay

Not sure? Start with DDD — you can evolve later. See Choose a Path for a detailed comparison.


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


    10-chapter tutorial from your first aggregate to production.

    Tutorial

  • How Do I...?


    Task-oriented index — look up what you're trying to do and jump straight to the right guide.

    How Do I...?

  • Guides


    Step-by-step instructions for every task Protean supports.

    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