Transactions across every provider.
Some providers support 2PC. Some only support local transactions. Some support nothing — Cassandra, Redis, Neo4j cross-session writes. Vadyl picks the right strategy based on declared DbCapabilities, registers compensation for every mutation, and walks the saga LIFO if anything fails partway. You write business logic. Vadyl writes the rollback.
Pick the strategy from the declared capabilities.
DbCapabilities.Transactions describes what each provider can do — Supports2Pc, SupportsSavepoints, SupportsCompensationOnly. Vadyl reads that, picks the strategy, and never falls back to a weaker mode silently.
Native transactions where possible
Single-provider operations use the provider's native transaction. SQL Server, PostgreSQL, MySQL, MongoDB sessions, Neo4j session-spanning transactions — all real, all participating in Vadyl's lifecycle.
Two-phase commit across providers
When two providers both support 2PC, Vadyl coordinates a real distributed transaction. Prepared phase, commit phase, rollback on any participant failure.
Saga compensation everywhere else
Cassandra has no XA. Redis has no transactional cross-key. Mixed-provider DAGs are the norm. Vadyl registers a compensation for every mutation and walks the saga LIFO on failure.
Priority-LIFO rollback. DELETE → UPDATE → INSERT.
CompensationAction.Priority is the canonical ordering rule: DELETE = 30, UPDATE = 20, INSERT/LINK = 10. Sorted descending, LIFO within priority. Constraint violations during rollback minimized by construction.
Pre-mutation snapshots
WriteCoordinator captures a snapshot WITH the access filter applied — so compensation correctness honors RLS even when restoring deleted rows.
Type-aware re-insert
ForDelete compensation filters out identity columns on re-insert. No identity-insert errors. Provider-specific quoting and casting handled in the AST, not the saga.
Cross-storage compensation
Document writes get DocumentMutationPlan compensation. Graph mutations get UpsertVertex / UpsertEdge inverses. KV writes get KvDelete / KvPut-with-prior-value. All execute through canonical executors.
Cancellation-safe
Rollback uses CancellationToken.None. A cancelled caller token never silently prevents cleanup — anti-pattern #18 codified at every site.
Compensation audit
Every compensation invocation surfaces in the canonical observability relay. The audit trail shows what failed, what compensated, what state the world ended up in.
Saga visibility
Operations expose their compensation chain through the explainability plane. You can ask Vadyl exactly what would roll back if step N fails — before you commit.
Pick the strictness, see the actual achieved level
Strict
If compensation is unavailable for any step in the operation, Vadyl refuses to start. Deny-by-default for write paths that cannot be made consistent.
Use when correctness > availability
Standard default
If compensation is unavailable, Vadyl proceeds, logs the degradation, increments a metric. vadyl.document_writes.guarantee_degradations.total
The everyday default
BestEffort
Proceeds silently. Use when you've decided availability matters more than guaranteed consistency. Use sparingly — and audit the trail.
Explicit, never the silent default
Every WriteCommitResult reports ActualGuaranteeTier — the achieved level, not the requested one. Honesty over hand-waving.
DELETE / UPDATE / INSERT
Deterministic, last-in first-out
Strict / Standard / BestEffort
Every fall-through is metered + logged
Stop writing manual rollback scripts.
Vadyl tracks every mutation and registers compensation. If step N fails, it walks the saga backwards until the world is consistent. Your code expresses intent. The platform handles consistency.