Asset Transactions and Save Boundaries
Summary
Source-backed description of how the Asset Service commits work — a single local database transaction per save that carries the aggregate, its children, evidence, and outbox rows together — and how external HTTP calls to the Workflow and Document Services sit outside that transaction with no distributed atomicity.
Audience
Backend engineers, database reviewers, architects, QA, support, operations, security reviewers, and product owners.
Overview
Every Asset write is committed through AssetDbContext.SaveChangesAsync, which dispatches domain events to the outbox and then calls the base save. EF Core wraps that save in one implicit local transaction — there is no explicit BeginTransaction. External integrations happen over HTTP before or after the save and are not part of the transaction.
Confirmed persistence behavior
Save model
UnitOfWork.SaveChangesAsyncdelegates toAssetDbContext.SaveChangesAsync, whose override first runsDispatchDomainEventsToOutbox()(mapping domain events to contract integration events, guarded byEnsureComplete), then calls the base save.- The save is one implicit local database transaction (EF Core's default). There is no explicit
BeginTransactionanywhere in the source and no distributed transaction or two-phase commit. - When they are staged before the call, the following commit together in that one transaction: the
Assetaggregate row, its assignment-history rows, its document-reference rows, the audit rows, the timeline rows, and the outbox rows. Integration events are therefore durable if and only if the local save commits.
External calls relative to the transaction
External HTTP calls are made from the application layer, outside the DbContext transaction:
- Workflow Service (
WorkflowIntegration): on the create-request path the asset is saved first, the workflow start/verify call is made next, and a second save attaches the returned instance id. The workflow call is never inside the asset's save transaction. - Document Service (
DocumentIntegration): the store call happens before the document-reference row is saved, so bytes land in the Document Service first and only a reference is then persisted. Download is a read-only pass-through. File bytes are never stored in the Asset database.
Distinct boundaries to keep separate:
- State staged before
SaveChangesAsync— aggregate mutation plus audit/timeline writer rows are queued in the unit of work. - Committed in one local transaction — the override adds outbox rows, then the base save commits everything staged atomically within the Asset database.
- External calls before or after persistence — Workflow and Document Service HTTP calls bracket the save but do not join it.
- No distributed atomicity — there is no shared transaction spanning the Asset database and the external services.
Failure behavior
- Domain validation failure →
DomainValidationExceptionsurfaced as HTTP 400; nothing is saved. - Workflow start failure → in Production the create fails; in Development it falls back to a plain
Requestedasset (no workflow instance). - Document Service unavailable → HTTP 503 fail-safe; because bytes are stored before the reference is saved, bytes are never dropped, but a reference is not persisted for a failed store.
- External-succeeds / local-save-fails window → there is no compensation. If a Workflow or Document Service call succeeds and the subsequent local save fails, the source performs no rollback of the external effect.
Classification
Implemented single local-transaction save with in-transaction outbox staging; external integration is Transitional and non-transactional, with no compensation.
Requires confirmation
Operational handling of the external-succeeds/local-fails window and any future need for a compensation or reconciliation path require confirmation.
Diagram
Related Articles
See Also
Keywords
- Asset persistence
- Transactions and Save Boundaries
- Draft database documentation
Source References
microservices/src/asset-service/Infrastructure/AssetDbContext.csmicroservices/src/asset-service/Application/Commands/AssetCommands.csmicroservices/src/asset-service/Application/DocumentIntegration.csmicroservices/src/asset-service/Application/WorkflowIntegration.cs
Revision Information
- Status: Draft
- Last reviewed: 2026-07-17
- Review cycle: Quarterly