2 min readCalm pace · scan the outline anytime

Reads and reporting

Cross-context queries without ORM relations across modules — ACL reads, projections, and owned read models.

Reads and reporting

Write-side replaceability is wasted if reports join every module’s tables through ORM relations. Treat cross-context reads as deliberately designed contracts.

Related: Ports & persistence · ACL · Events.

Ownership

DataOwner
Authoritative write modelThe bounded-context module that defines the invariant
Cross-module foreign keys for business joinsAvoid as a coupling mechanism (Core FR-6)
Denormalised read model / projectionThe module (or host reporting app) that needs the screen — fed by Events or sync ACL

Patterns (allowed)

1. Sync ACL read

UI → Use Case → local read port → ACL → peer façade method that returns a small DTO (not Entities, not ORM).

Use for: eligibility checks, availability, “display peer label for this code.”

2. Event-sourced projection (preferred for lists/dashboards)

Publisher emits rich events → consumer/reporting Infrastructure translation listener → updates a local read table owned by the reader.

Use for: warehouse “open orders” board, directory “member activity” summaries.

3. Host reporting composition (outer layer)

A reporting UI/module in Infrastructure/UI may call multiple ACL façades or read replicas as an outer composer — still without putting foreign Domain types into another module’s Application/Domain.

Do not hide that composition inside a random Domain Entity.

Patterns (forbidden)

SmellFix
ORM associations / joins across module namespaces for policyACL or projection
Shared “ReportModels” with everyone’s columnsOwned projection per consumer
Use Case running raw SQL across peer schemasPeer façade / projection

Practical guidance

  1. Screens that need one peer field → ACL read or denormalise a code + label via Event.
  2. Screens that need many rows from peers → projection updated asynchronously.
  3. Analytics warehouses / BI → export from each module or from projections; out of Core scope, but still not an excuse for Domain coupling.

Next: Identity ↔ Directory cookbook · anti-patterns.

Modular Hexagonal Domain-Driven Design
Core 1.0.0-draft