Sketch aggregates, events, and bounded contexts. In Protean that model is the architecture, and everything else, the API, the docs, the contracts, is derived from it.
@domain.aggregate class Order: customer_id: Identifier(required=True) status: String(max_length=20, default="draft") items = HasMany("OrderItem") @invariant.post def must_have_items_when_placed(self): if self.status != "draft" and not self.items: raise ValidationError(...) # rejected at construction. invalid state cannot exist. Order(customer_id="c-1", status="confirmed") ValidationError: Order must have at least one item
Four capabilities, each one following from a single idea: the model is the source of truth, and it is trustworthy enough to build everything else on.
Protean parses your model into a machine-readable Intermediate Representation. Docs, API specs, and contracts are derived from it, so they cannot drift from the code.
Domain objects are always valid, or they do not exist. Four layers of validation run on every change, and the structure is checked before the first request.
Start with plain domain-driven design. Add CQRS or event sourcing for one aggregate at a time, in the same codebase, with no rewrite.
Your domain knows nothing about databases, brokers, or caches. You swap them in configuration, and the model, the tests, and the rules stay untouched.
Add a field to an Order in most stacks and you touch it in nine places: the model, the migration, the schema, the spec, the client types, the docs, the fixtures, the event, the version.
In Protean you touch the model. Everything that can be derived is derived, so the drift that pulls a real system away from its own drawing has nowhere to enter.
One source of truth, an always-valid domain, and why both matter more now that machines write the code.
Built for backend systems whose hard part is the business rules and the states things move through. It is honest about where it stops. Is Protean for you?