Skip to main content

Protean

Protean is an opinionated Python framework for building event-driven applications with Domain-Driven Design — aggregates, CQRS, and event sourcing are first-class, and your domain logic stays independent of the database, broker, and API you run it on.

Python Release Build Status Coverage Tests Maintainability

🗺️ Roadmap: where Protean is headed next, and the current milestone for the issue-by-issue detail.

Installation

Protean is available on PyPI:

$ pip install protean

Protean officially supports Python 3.11+.

Quick Start

A command flows to its handler, the aggregate raises an event, an event handler reacts, and a projector keeps a read-optimized feed in sync, all wired by the domain, independent of infrastructure:

from protean import Domain, current_domain, handle
from protean.core.projector import on
from protean.fields import Identifier, String, Text

domain = Domain()


@domain.aggregate
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))


@domain.event(part_of=Post)
class PostPublished:
    post_id: Identifier(required=True)
    title: String(required=True)


@domain.command(part_of=Post)
class PublishPost:
    title: String(max_length=100, required=True)
    body: Text(required=True)


@domain.command_handler(part_of=Post)
class PostCommandHandler:
    @handle(PublishPost)
    def publish_post(self, command: PublishPost):
        post = Post(title=command.title, body=command.body)
        post.publish()
        current_domain.repository_for(Post).add(post)
        return post.id


@domain.event_handler(part_of=Post)
class PostEventHandler:
    @handle(PostPublished)
    def announce(self, event: PostPublished):
        print(f"Event handled: post published ({event.title})")


@domain.projection
class PublishedPostsFeed:
    """A read-optimized feed of published posts."""

    post_id: Identifier(identifier=True, required=True)
    title: String(max_length=100, required=True)


@domain.projector(projector_for=PublishedPostsFeed, aggregates=[Post])
class PublishedPostsFeedProjector:
    """Maintains the PublishedPostsFeed projection from Post events."""

    @on(PostPublished)
    def on_post_published(self, event: PostPublished):
        feed_entry = PublishedPostsFeed(post_id=event.post_id, title=event.title)
        current_domain.repository_for(PublishedPostsFeed).add(feed_entry)


if __name__ == "__main__":
    domain.config["command_processing"] = "sync"
    domain.config["event_processing"] = "sync"

    domain.init(traverse=False)

    with domain.domain_context():
        # Write: publish a post through the command.
        post_id = domain.process(
            PublishPost(title="Hello, Protean!", body="My first published post.")
        )
        post = domain.repository_for(Post).get(post_id)
        print(f"Post created: {post.title} (status: {post.status})")

        # Read: the projector has already filled the feed inline.
        feed = domain.view_for(PublishedPostsFeed).query.all()
        print(f"Published posts feed: {feed.total} row(s)")
        for entry in feed.items:
            print(f"  - {entry.title}")

Reference application

For a fuller picture, examples/reference_app/ runs the same blog domain behind a FastAPI app. See app/README.md for setup and the routes it exposes.

For a larger, multi-context example, see proteanhq/shopstream, a shopping platform built with Protean.

Documentation

Online docs are available at https://docs.proteanhq.com.

Versioning

Protean does not use strict semantic versioning. The promise is: Code that runs warning-free on 1.N runs unmodified on 1.N+1. Every removal is announced by a deprecation warning naming the release it lands in, at least one release ahead, so you can turn "will this upgrade break us?" into a test run. See the versioning policy for the full contract.

Quality

Every commit runs the in-memory core suite across 5 Python versions and all 5 backing services on the newest stable Python; the full adapter matrix across every version runs nightly.

Metric Value
Tests 12,000+ (quality report)
Linting Zero violations (Ruff)
Complexity Avg 3.38 cyclomatic (A grade)
Maintainability A rank (95% of files)
CI Matrix Python 3.11-3.14 + 3.15 prerelease; PostgreSQL, Redis, Elasticsearch, MessageDB, MSSQL on the newest stable per PR, full matrix nightly

See the full Quality Report for details.

Contributing

Note: Protean framework is not associated or related to Protean eGov Technologies or Code for Gov Tech initiatives.

Protean is developed and maintained by a single maintainer. The contributions that help most are bug reports, real-world use cases, and adapter packages built against the public conformance suite.

  • Have a question, or a real-world use case to share? Start a discussion. Questions are answered there, and the thread stays searchable for the next person who hits the same thing.
  • Found a bug? Open an issue. Clear, reproducible reports are the most valuable contribution you can make, and they are answered as a priority.
  • Planning a non-trivial code change? Open an issue to discuss it first, before investing in a pull request. Unsolicited large PRs may not be merged. Small, obvious fixes are welcome directly.
  • Building an adapter? Adapters live in their own packages, certified against the conformance suite. See the contributing guide.

See CONTRIBUTING.md and the community section for the full picture.

License

Protean is licensed under the Apache License 2.0.

Licensing commitment. The Protean framework core is, and will remain, available under the Apache License 2.0. This is a permanent commitment: the core will not be relicensed to a proprietary or source-available license.

Copyright 2018-2026 Subhash Bhushan C and the Protean contributors.

Metadata

Release files for protean 0.18.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for protean 0.18.1
File Size Uploaded Provenance Actions
protean-0.18.1.tar.gz 7.4 MB With provenance Details for protean-0.18.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for protean 0.18.1
File Interpreter ABI Platform Actions
protean-0.18.1-py3-none-any.whl Python 3 none any Details for protean-0.18.1-py3-none-any.whl

Total release size: 9.8 MB

Release files / protean-0.18.1.tar.gz

Download URL protean-0.18.1.tar.gz
Size 7.4 MB
Tags Source
SHA-256 checksum
How to use checksums
fd1b2c6d5a71c8ccafc8ec359d14c3b26e9aaf37ecde20af4bbcf0635a646c72
BLAKE2b-256 checksum
How to use checksums
a8f5c92ba8618d7d60162077fea03dd5e97d174313377d02f37e99d3d7ef1ace
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Release files / protean-0.18.1-py3-none-any.whl

Download URL protean-0.18.1-py3-none-any.whl
Size 2.4 MB
Tags Python 3
SHA-256 checksum
How to use checksums
6575be8127bc51a988b43d6bab1f80862b4f26a8d78823b6cf7a95e73738a3ea
BLAKE2b-256 checksum
How to use checksums
c731f2f285f3de5106493c32e07193356ff4f7521cd652db6da30fe04ada6556
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Security for protean 0.18.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for protean-0.18.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.18.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page