Reconciliation and drift
In which order must writes to two stores happen, and how do you detect the rest?
Two stores that cannot be updated atomically will diverge. Divergence goes in two directions with very different costs:
| Situation | Name | Effect |
|---|---|---|
| Files exist but no metadata points to them | orphans | waste money; threaten nothing |
| Metadata points to files that do not exist | dangling references | queries fail hard |
That asymmetry dictates the order of writes:
- On write: data first, then metadata.
- On delete: metadata first, then data.
- Never the reverse.
If a crash happens between the two steps, the first order leaves an orphan (harmless) and the second never leaves a dangling reference. This is the same discipline as the write-ahead log (a database writes its intention to a log before changing the data pages) and the transactional outbox (a service stores "message to send" in the same database transaction as its change, and sends later). The general rule:
Detection is expensive. A reconciliation scan is O(files) LIST operations, each with a per-request price. So how often to scan is an economic decision.
Orphan deletion needs an age threshold longer than the longest possible in-flight write, or you delete files that a slow writer is about to commit. That threshold is an assumption the system cannot verify. When it fails, the one who pays is the writer whose eight-hour job has its output collected out from under it. The same shape returns with usage-based deprecation.
Order cross-store writes so the survivable inconsistency is the one that occurs. Detect the rest at a cadence you can afford.