A commit on S3 is one compare-and-swap
A search cluster has a coordinator. A bucket does not. If Infino is going to hold the only searchable copy of a table, a crash during a write cannot leave that table torn. The durability boundary has to be something the object store already knows how to do.
That boundary is one conditional write on a single pointer.
Immutable files are not enough
The simplest write path would upload a new data file and add its name to a list. It works until the writer crashes between those operations, or two writers read the same list and each publish a different replacement. Immutability protects file contents; it does not say which set of files forms the table.
Step 1: stage everything in parallel
We never edit a file. A writer stages new superfiles and manifest parts in parallel. Each manifest part is named by the blake3 hash of its bytes, so two writers that produce the same part target the same object. If the second create loses its precondition race, the write is still complete: the object already contains the expected bytes.
Step 2: publish one pointer
None of those staged objects is reachable from the current table version. Readers follow only _supertable/current. A commit becomes visible when the writer conditionally replaces that pointer with put-if-match against its previous ETag, or create-if-absent for the first commit. On local disk, where there is no ETag, the same swap runs under an advisory file lock.
Crashes and races
A crash during staging leaves orphaned objects, not a partial table. The pointer still names the previous complete version, so readers never discover the abandoned files. Garbage collection removes them later.
When two writers race, one wins the compare-and-swap. The other sees a stale ETag, reloads the new current manifest, rebuilds its commit on top, and retries. A query pins one manifest at the start, so a commit that lands later cannot change the files beneath that query.
Deletes follow the same rule. A delete adds a roaring-bitmap tombstone rather than rewriting the data file. The manifest pins both the files and the tombstones that apply to them, so rows cannot disappear halfway through a query.
Why there is no lock service
The object store already arbitrates the only contested operation. A writer must replace exactly the pointer version it read. If that ETag is stale, the write fails without changing the pointer; the writer reloads the winning manifest and retries its change on top.
An external lock or consensus service would still need a durable publication record after granting the lock. Using the pointer as both the publication record and compare-and-swap boundary removes that extra state from the commit path.
Only the pointer swap is serialized
Data files and manifest parts are written in parallel; only the final pointer update is serialized. On a 10-million-document table on real S3 (8 cores, 256 superfiles, 16 commits), the same path ingested about 33,100 docs/s full-text and 62,200 docs/s vector at dimension 384.
The invariant is the reason this works without a coordinator: stage any amount of data, but publish exactly one pointer. A reader sees the complete version before that swap or the complete version after it.