Conditional Writes

Coordinate multiple writers using If-Match and Stream-Seq without adding locks or transactions.

Multiple writers appending to the same stream may need coordination. Ursula supports two forms of optimistic concurrency control via request headers, without locks or transactions.

If-Match

If-Match guards an append against a stale view of the stream. The value is an ETag returned by a previous HEAD or read response. If the stream's current ETag doesn't match, the server rejects the append with 412 Precondition Failed.

# Get the current ETag
etag=$(curl -s -I 'http://127.0.0.1:4437/demo/hello' | grep -i etag | tr -d '\r' | awk '{print $2}')

# Append only if nobody else has written since
curl -X POST http://127.0.0.1:4437/demo/hello \
  -H 'Content-Type: application/octet-stream' \
  -H "If-Match: $etag" \
  --data-binary 'conditional update'

Use this when your write depends on the stream being in a known state. For example, a CRDT client that only wants to append if its local view is up to date.

Stream-Seq

Stream-Seq is a client-supplied monotonic sequence token. The server tracks the last accepted value per stream and rejects any append whose Stream-Seq is not lexicographically greater than the previous one.

This is useful when a single logical writer wants to enforce ordering without relying on server-side ETags. For instance, an agent that numbers its steps and wants the server to reject out-of-order delivery.

When to use which

  • If-Match: multi-writer coordination. "Only write if the stream hasn't changed since I last looked."
  • Stream-Seq: single-writer ordering. "Reject this if my writes arrive out of order."
  • Neither: append-only workloads where every write is independent (e.g. event logging). Just POST.