ADR-0037: retain asynchronous persistence¶
Status: accepted. FS-19 explicitly permits either verified synchronous persistence or an evaluated, clearly documented async-only contract. Retain async-only persistence; this completes that decision, not synchronous EF parity.
The pinned Neo4j.Driver 6.3.0 contract used by the provider exposes IDriver.AsyncSession, asynchronous transaction begin/commit/rollback and asynchronous cursor consumption. The current save path also performs schema reads, lock/mutation statements and async resource cleanup. A wrapper around SaveChangesAsync().GetAwaiter().GetResult() would block its caller throughout that work. Moving it to Task.Run would still block the caller and introduce worker scheduling; it would not establish native synchronous transport or cheaper hosting.
Such a bridge would require evidence for custom synchronization contexts, thread-pool pressure, ambient execution context, explicit transaction ownership, exception propagation, disposal and uncertain commit behavior. Avoid claiming that every host necessarily deadlocks: the specific risk depends on implementation and hosting. There is no accepted consumer requirement or measured hosting benefit that justifies this added contract now. A separate synchronous implementation would duplicate a correctness-sensitive transaction path. Preserve the established async API instead.
Neo4jDatabase.SaveChanges continues to throw NotSupportedException directing callers to SaveChangesAsync. Pending inserts, updates and deletes reject before provider transport. The public default and both Boolean acceptance modes are covered. Existing transactions remain under caller control. EF can still run change detection and application interceptors/events before reaching the provider; do not describe the entire public call as side-effect-free. User interceptors can also suppress execution.
EF 10.0.12 StateManager.SaveChanges returns zero before provider dispatch when there are no entries to save. Consequently an unchanged context can return zero from synchronous SaveChanges, including both acceptance modes. That shortcut proves no synchronous persistence capability. Do not replace EF's state manager solely to make that no-op throw.
Eleven new cases in SaveChangesFailureTests pass within all 711 provider unit cases, zero failures/skips, build zero warnings/errors. Nine cases use actual EF tracked entries through the production database service and assert no driver call, preserved pending values/state, and a subsequent asynchronous save through the existing scripted protocol. One verifies that rejection leaves a borrowed explicit transaction untouched; one verifies the unchanged-context shortcut. These are client-state/transport-boundary tests, not new server persistence evidence. No runtime implementation changed, so no database fixture or hosted workflow was needed. Existing live async-save evidence remains in ADR-0013 and ADR-0026.
Use asynchronous APIs throughout application callers; a library hard-coded to synchronous persistence is outside the supported contract. Reconsider only for a concrete consumer and separately measured hosting/lifecycle acceptance, captured under FUT-10. Supporting synchronous context metadata/disposal in the FS-18 sample does not imply synchronous database operations.