An offline-first branch system needs a clear contract for what can happen locally. Start with the workflows that must survive a connection failure, then identify the decisions that require current central data. A local interface alone does not make a system offline-first.
Define the boundary of local operations
Order capture, draft storage, and cached information may have a local path. An online payment authorization or a global credit decision may still depend on an external service. Show whether an operation is recorded locally, awaiting synchronization, or confirmed centrally. Avoid treating those states as interchangeable.
What the transactional outbox solves
A database write can succeed while publishing its notification fails. Recording the business change and an outbound event in one local transaction gives a worker something durable to deliver later. AWS describes the dual-write problem and the transactional outbox pattern.
For this design, give each event a stable identifier, source branch, type, contract version, and necessary payload. Also define storage capacity, acknowledgement handling, and retention. An outbox table does not make those operational decisions for you.
Idempotency makes retries safe
The destination might store an event but lose its acknowledgement. The sender retries. A destination uniqueness constraint can record the event identifier alongside its business effect in one transaction. A duplicate request should return the existing outcome instead of creating another order.
Create the identifier when the operation starts. Generating a new identifier on every attempt prevents duplicate detection. Test interrupted requests as well as successful ones.
Conflict resolution follows business semantics
Orders, configuration, and inventory do not share one conflict policy. Define which location owns a change, what ordering matters, and when human review is necessary. Two inventory changes cannot always be resolved by choosing the latest timestamp; device clocks can disagree too.
Recovery and visibility belong in the protocol
Use bounded retry scheduling with backoff and jitter. Make incompatible events visible so they do not block all later work indefinitely. Useful operational signals include queue size, age of the oldest event, repeated failures, and last successful synchronization. A full local disk deserves an explicit failure path.
A practical failure-test checklist
- Disconnect after local commit but before delivery, then verify recovery.
- Drop the destination acknowledgement and confirm that retry adds no second effect.
- Stop the synchronization worker during delivery and restart it.
- Exercise old event versions, malformed payloads, and limited local storage.
See the CafeChee architecture brief for branch-operation context. Progressive edge delivery and rollback covers releasing software to independent nodes.