Skip to content

ADR-0006: NHibernate as the primary ORM

Decision

This page records a decision and its status. A Proposed decision is not binding; an Accepted decision is binding on the Factory until amended or superseded.

  • Status: Accepted
  • Date: 2026-01-01
  • Deciders: Data Architect, Backend Lead
  • Tags: persistence, data, orm

Reviewed 2026-10-09 — retained, clarified

  • Disposition: retain.
  • Verified: NHibernate is the persistence of BaseTemplate, the five SaaS templates, the Orleans messaging outbox writer and all nine DerechHaLev services; canonical ADR-0100 also assumes NHibernate for SaaS services.
  • Clarification: "Document-shaped data uses Cosmos DB" is a profile option, not a requirement; no Cosmos integration was inspected. Per-context store ownership is specified in the ownership map, not implied by this ADR.
  • Provenance: Date is the 2026-06-17 bulk-commit value.

Context

Transactional metadata (aggregates, registries, lifecycle state) is stored in Azure SQL / PostgreSQL with a database-per-service model (see Data Architecture). The platform needs a mature ORM that supports rich domain mapping for DDD aggregates, row-level tenant filtering, and second-level caching, and is already grounded in the ConnectSoft.Extensions.* data libraries and templates.

Decision

Use NHibernate as the primary ORM for transactional stores. Tenant isolation is enforced through tenantId participation in indexes and row-level filtering in NHibernate; each store has a single owning service.

Consequences

Positive

  • Rich mapping for DDD aggregates and value objects; mature filtering and caching.
  • Consistent data-access pattern baked into templates.

Negative / trade-offs

  • Mapping/configuration learning curve; care needed for query performance.

Neutral

  • Document-shaped data uses Cosmos DB rather than the relational ORM.

Alternatives considered

Alternative Why not chosen
Entity Framework Core Viable, but platform libraries/templates are standardized on NHibernate.
Dapper / micro-ORM Insufficient domain-mapping and filtering for aggregate-heavy domains.