# Architecture
> Event sourcing, CQRS, workspace isolation, and the internals of Syntropic137
## Event Sourcing
Syntropic137 uses **event sourcing** as its core persistence pattern. Instead of storing current state, every state change is recorded as an immutable event. The current state is derived by replaying events.
### Two Event Types
Syntropic137 distinguishes between two kinds of events, each optimized for its use case:
| | Domain Events | Observability Events |
|---|---|---|
| **Purpose** | Business logic, state transitions | Telemetry, metrics, audit logs |
| **Storage** | TimescaleDB (append-only, replay-safe) | TimescaleDB (hypertable, time-series optimized) |
| **Pipeline** | Command → Aggregate → Event → Projection | Agent stdout → Collector → EventBuffer → TimescaleDB |
| **Validation** | Aggregate invariants, can be rejected | Schema validation only, append-only |
| **Examples** | `WorkflowCreated`, `ExecutionStarted` | `ToolExecuted`, `TokensUsed` |
## CQRS
Commands and queries are strictly separated. Commands modify state through aggregates; queries read from pre-built projections cached in Redis.
**Commands (12):** `CreateWorkflow`, `StartExecution`, `PauseExecution`, `ResumeExecution`, `CancelExecution`, `RegisterTrigger`, `UpdateTrigger`, `DeleteTrigger`, and more.
**Events (31):** Every command produces one or more events: `WorkflowCreated`, `ExecutionStarted`, `ExecutionPaused`, `ExecutionResumed`, `ExecutionCompleted`, `TriggerRegistered`, etc.
**Projections (14):** Pre-computed read models updated by event processors, cached in Redis or PostgreSQL for sub-millisecond query response times. Includes a `repo_correlation` projection that maps repositories to workflow executions for cross-context insight queries.
## Domain Model
Syntropic137 is organized into five bounded contexts with nine aggregates:
## Real-Time Communication
Syntropic137 uses **Server-Sent Events (SSE)** for real-time monitoring of executions — progress updates, tool events, token metrics, and state changes all stream over a single connection:
```
GET /api/executions/{execution_id}/stream
```
Control commands (pause, resume, cancel) are sent via standard REST API calls rather than a persistent connection.
### Execution State Machine
NOT_STARTED
→ start →
RUNNING
→ finish →
COMPLETED
RUNNING
→ error →
FAILED
RUNNING
→ pause →
PAUSED
→ resume →
RUNNING
RUNNING
→ interrupt →
INTERRUPTED
→ retry →
RUNNING
PAUSED
→ cancel →
CANCELLED
**Yield Points** — The agent can only be paused at safe points: before each workflow phase, after each tool execution, and after each LLM call.
## Performance
Both event pipelines are optimized for their access patterns. Domain events use append-only writes with aggregate-level consistency. Observability events use TimescaleDB hypertables with automatic partitioning for high-throughput ingestion. Read models are cached in Redis for fast dashboard and API queries.