Postgres read models (query side)
Chronacta remains the source of truth. JSON projections under data/projections/ stay for lightweight ops. Postgres is an external read model owned by the query/UI team.
Ownership
Section titled “Ownership”| Artifact | Owner | Location |
|---|---|---|
| Domain events | Domain/backend | Schema Registry + publishers |
| Postgres table schema | Read model team | YAML read-model schema |
| DDL / DML SQL | Generator from YAML | migrations/*.sql + runtime statements |
| Event → column mapping | Read model team | source: fields in YAML |
| JSON projections | Ops / Chronacta CLI | data/projections/ |
Chronacta does not create Postgres DDL at runtime and does not invent table schemas.
schema.yaml → chronacta sqlgen generate ddl → migrations/*.sql → apply → runtime DML from YAML → postgres projector → UPSERTChronacta durable subscription ───────────────→ postgres projector → ACK after commitYAML schema
Section titled “YAML schema”See examples/postgres-projector/schema.yaml. Columns declare source paths such as:
event.event_idevent.event_typeevent.stream_idevent.global_positionevent.created_atevent.data/event.data.<field>event.metadata.<key>
SQL generator
Section titled “SQL generator”./bin/chronacta sqlgen generate ddl \ -schema examples/postgres-projector/schema.yaml \ -out examples/postgres-projector/migrations
./bin/chronacta sqlgen generate dml \ -schema examples/postgres-projector/schema.yaml \ -out examples/postgres-projector/generatedReview generated DDL before applying. Runtime does not run CREATE TABLE.
Projector
Section titled “Projector”Use chronacta-connector with handler go:PostgresReadModel and Postgres settings in the job config (see examples/postgres-projector/connector.yaml).
Delivery semantics:
- Pull event from durable subscription
BEGIN- Insert into
processed_events(ON CONFLICT DO NOTHING) - If inserted: execute generated UPSERTs + checkpoint
COMMITthen ACK- On Postgres error: do not ACK (Nack / retry)
At-least-once; consumers must tolerate redelivery via event_id idempotency.
Rebuild / schema evolution
Section titled “Rebuild / schema evolution”- Edit
schema.yaml - Regenerate DDL (
sqlgen generate ddl) — v1 prefers new migration or full rebuild, not auto-ALTER - Stop projector
- Apply migration
- On breaking change:
TRUNCATEdomain tables (+ optionalprocessed_events), reset subscription checkpoint / replay - Start projector and wait for lag to clear
JSON Chronacta projections are unchanged by this process.
Health and metrics
Section titled “Health and metrics”Projector logs event_id, stream_id, global_position, event_type, table name. Do not log payloads or secrets by default.
Operational checks:
- Chronacta reachable
- Postgres ping
- Subscription lag
- Duplicate skips vs upsert errors

