Building Business Logic
This section covers everything you need to implement business capabilities in PURISTA: services, commands, subscriptions, streams, queues, schemas, error handling, and more.
The builder pattern
PURISTA uses a fluent builder API for every artifact. Each builder collects metadata, schemas, and functions, then produces a typed definition.
flowchart LR
SB["ServiceBuilder"] -->|getCommandBuilder| CB["CommandBuilder"]
SB -->|getSubscriptionBuilder| SUB["SubscriptionBuilder"]
SB -->|getStreamBuilder| ST["StreamBuilder"]
SB -->|getQueueBuilder| QB["QueueBuilder"]
CB -->|getDefinition| CD["CommandDefinition"]
SUB -->|getDefinition| SD["SubscriptionDefinition"]
ST -->|getDefinition| STD["StreamDefinition"]
QB -->|getDefinition| QD["QueueDefinition"]
CD -->|add to| S["Service"]
SD -->|add to| S
STD -->|add to| S
QD -->|add to| S
Core concepts
| Concept | Purpose | Pattern |
|---|---|---|
| Service | Business boundary with metadata, config, and resources | Domain-driven grouping |
| Command | Typed request/response operation | Active, synchronous |
| Subscription | Reaction to events matching filters | Passive, asynchronous |
| Stream | Multi-frame response for live updates | Push, real-time |
| Queue | Pull-based async work with workers | Durable, background |
| Schema | Zod-based validation and TypeScript types | Boundary enforcement |
| Store | Config, secret, and state persistence | Externalized state |
Suggested reading order
Follow this path to build a complete mental model:
- Builders — understand the builder pattern and shared configuration
- Schemas & Validation — define Zod schemas for inputs, outputs, and events
- Service — create a service with metadata, config, and resources
- Command — add request/response operations with guards and transforms
- Stream — implement live, incremental responses
- Subscription — react to events from other services
- Queue — handle durable background work
- AI Agents — add LLM-powered workflows (optional)
- Custom Events — emit and handle domain events
- Error Handling — structured errors and recovery
- Logging — structured logging with context
- Stores — config, secret, and state management
- Exposing Commands — REST, SSE, and GraphQL
- HTTP Client — call external APIs with typed clients
- Connect to PURISTA — build clients for your services
- Advanced — message structure, delivery semantics, protocol internals
How the pieces fit together
flowchart TB
subgraph Client["External Client"]
REST["REST / SSE"]
GQL["GraphQL"]
end
subgraph PURISTA["PURISTA Application"]
direction TB
EB["Event Bridge"]
S1["User Service"]
S2["Order Service"]
S3["Email Service"]
Q["Queue + Worker"]
end
subgraph Infra["Infrastructure"]
Broker["Message Broker"]
DB["Database"]
Cache["Cache"]
end
REST -->|HTTP| EB
GQL -->|HTTP| EB
EB -->|commands| S1
EB -->|commands| S2
EB -->|events| S3
S1 -->|enqueue| Q
Q -->|worker| S1
S1 <-->|resources| DB
S2 <-->|resources| Cache
EB <-->|transport| Broker
Key design guidelines
- One service per business capability — not per technical layer
- Commands are named operations —
userSignUp, notPOST /users - Subscriptions are decoupled — the producer does not know the consumer exists
- Schemas at every boundary — no untyped data enters or leaves a service
- State externalized — use stores, not in-memory state
- Errors are typed — return
UnhandledErroror custom error schemas
Next: start with Builders to understand the foundation of every PURISTA artifact.