Synthetic fixtures; deterministic local model. No production system is contacted.
Experiment inputs
Complete-run results
Decision trace
What this experiment demonstrates
A small JSON object in an object store records how many publications happened today, which run is active, and a history. Several publishers start within the same second. Each one reads the object and its entity tag, checks the daily cap and the active lease, writes an updated object, and then uploads; when it finishes it clears the lease. The page models the store with the semantics of S3 conditional writes: an unconditional PUT always succeeds, a PUT with If-Match succeeds only if the tag is unchanged and otherwise answers 412, a PUT with If-None-Match succeeds only when the object does not exist, and reads are strongly consistent.
The publishers are fixed programs that behave the same way every run, so every difference in the outcome comes from a control you changed: how many publishers, which condition they use, how many retries they allow, whether the object exists at the start, and what happens to the winner of the first slot.
Run controlled comparisons
Start with the defaults: four publishers, a cap of two, If-Match on updates, three retries, two publishers racing at the same moment and two arriving half an hour later. The race winner reserves the first slot; the loser receives a 412, re-reads, sees the active lease and refuses, which is correct while an upload is running. The first later publisher finds the lease cleared and takes the second slot; the last one sees the cap and stops. Nobody loses an update. Switch the condition to none: both racers succeed, the second write silently replaces the first reservation, the ledger shows one slot used, two uploads run at once and a later publisher pushes the day past its cap. Set the retries to zero with If-Match: the loser gives up on its first 412 although a slot is still free.
Now untick the ledger existing before the run so that it has to be created. With If-None-Match on creation only one publisher creates it and the other re-reads; without the condition the second creation overwrites the first. Finally let the race winner die before finishing. With the lease refused, every later publisher stops and an operator must clear the lease; with the lease ignored, the evidence of the interrupted run is overwritten without inspection; with an expiry, later publishers proceed once the lease is older than the TTL, which is safe if the holder really died and unsafe if it is merely slow, as the slow option shows.
Notice what does not change. Every publisher reads the same object at the same moment. What decides the outcome is whether the write names the version it read, and what the system does with a lease that nobody released.
Inspect the trace and keep evidence
The attempt table lists each publisher's attempts: the tag it read, the condition it sent, the response, and what it did next, with the final ledger below it. Metrics count slots reserved, cap breaches, lost updates, concurrent uploads, conflicts answered with 412, publishers that gave up with a free slot remaining, refusals by an active lease, leases needing an operator and interrupted runs overwritten. Start trace, Next step, Show all and the slider control how much of the trace is visible; the metrics always describe the whole run. Reset restores the defaults and Export JSON downloads the inputs, the attempt table and the trace.
Limits and production translation
The store is a single object with perfect strong consistency and no request latency; arrival order is a control rather than a timing accident, and the 409 conflict that S3 returns for simultaneous conditional writes is folded into the 412 path, which has the same remedy. The upload itself is not modelled beyond its duration. What carries over: use If-None-Match to create and If-Match to update, retry from a fresh read on a conflict with a cap and jitter, keep the count and the lease in one object, and decide in advance who clears a lease whose holder died. An expiring lease needs a fencing check in whatever the holder writes, which an object store does not provide for you.