---
title: "Effectively-Once Processing with Single-Writer Entities"
subtitle: "A compact recipe for collapsing the producer-side dual write"
discipline: "Computer Science"
articleType: "Research Article"
authors: ["Dima Doronin"]
keywords: ["Distributed Systems", "Durable Objects", "exactly-once processing", "transactional outbox", "dual-write problem", "edge computing", "idempotency", "Cloudflare Workers", "message delivery semantics", "stateful serverless"]
date: "2026-07-18T15:29:27.916Z"
---

# Effectively-Once Processing with Single-Writer Entities

*A compact recipe for collapsing the producer-side dual write*

## Abstract

Effectively-once processing is not a delivery guarantee. It is a composition of local atomicity, retry, and exact duplicate suppression. This paper states the property over accepted logical commands and shows that it follows from four obligations: producer deduplication, atomic commit of state with durable intent-to-emit, a retrying relay, and exact consumer deduplication. A compact single-writer construction collapses the producer-side dual write into one local transaction, then hands the remaining duplicate boundary to a small receiver-side uniqueness check. A crash-boundary argument shows why the pattern achieves safety and liveness without assuming impossible exactly-once delivery, and why it still does not solve the output-commit problem or free cross-entity atomicity.

*Written July 2026. This note makes a general distributed-systems claim. It does not require a specific vendor runtime. It requires only a single writer per logical entity, local transactional durability, a relay that retries committed outbox rows, and exact duplicate suppression at the receiver.*

## 1. Problem statement

A producer often needs to do two things for one logical command: update durable state and emit a derived event. If those actions target different resources, partial failure can commit one without the other. That is the producer-side dual-write problem [1].

The right target is effectively-once processing over logical commands, not exactly-once delivery over a network. Once a sender has transmitted a message, it cannot in general distinguish lost message from lost acknowledgement. If it retransmits, duplicates become possible. If it stops retransmitting, loss becomes possible [1]. Duplicate delivery is therefore normal; correctness has to be recovered at the level of durable effects.

I will use two requirements:

- **Safety.** An accepted logical command changes downstream durable state at most once.
- **Liveness.** If a logical command was accepted and the transport continues retrying, the downstream durable state eventually reflects it once.

## 2. Four obligations

The target property follows from four obligations.

- **Producer deduplication.** One logical command creates at most one committed outbox row.
- **Atomic producer commit.** Producer state and durable intent-to-emit are committed in one local transaction.
- **Retrying relay.** Every committed outbox row is eventually emitted at least once.
- **Exact consumer deduplication.** Repeated deliveries of the same logical event are skipped rather than re-applied.

The second obligation removes the classic off-diagonal failure states of the dual write: state committed while event is missing, and event committed while state is missing [1,2,3]. The third obligation accepts duplicate delivery as the price of avoiding loss. The fourth obligation absorbs those duplicates at the only place they can no longer be removed by local atomicity.

## 3. Construction

Consider a runtime that offers one writer per logical entity and a local transactional store. Each entity keeps three structures together: its own durable state, a producer-side table of accepted command identifiers, and an outbox of events to be relayed.

A minimal producer is:

```text
submit(cmd):
  transaction:
    if cmd.idemKey already exists: return prior result
    validate cmd
    write producer state
    insert outbox row with fresh sequence
    record cmd.idemKey -> sequence
  schedule relay
  return success
```

The relay repeatedly scans committed unsent rows and emits them:

```text
drain():
  read unsent rows ordered by sequence
  send rows to transport
  mark exactly those rows sent
  if unsent rows remain: schedule another drain
```

The ordering of those two relay steps matters. Send must happen before mark. If a crash occurs after send but before mark, the same durable row is emitted again on restart. That is deliberate. The receiver is responsible for turning repeated delivery into a no-op.

A minimal consumer is:

```text
applyOnce(event):
  transaction:
    try to insert event key into applied set
    if key already exists: return
    fold event into durable projection
```

The applied set must have a uniqueness constraint on the event key. That constraint is what turns a duplicate transport event into zero additional durable effect.

## 4. Crash-boundary argument

The construction is small enough to check directly.

- **Before producer commit.** Nothing durable exists yet, so there is no torn state and no committed event intent.
- **After producer commit but before relay send.** Producer state, producer dedup entry, and outbox row already exist together, so the dual-write split is unreachable.
- **After relay send but before sent-mark commit.** The outbox row is emitted again after restart. This preserves liveness and shifts duplicate handling to the consumer.
- **During consumer apply.** The consumer transaction rolls back on crash, transport retries, and the uniqueness constraint prevents a second durable application once the first one has succeeded.

These four cases establish the target property. Producer deduplication plus consumer deduplication give safety. Retrying transport plus retrying relay give liveness for accepted commands.

## 5. Residual limit

The construction makes state update plus durable intent-to-emit atomic. It does not make state update plus external effect definitely happened atomic. That remaining gap is the output-commit problem discussed in rollback-recovery theory and in practical exactly-once stream processors [4,5]. If a producer cannot distinguish effect happened but acknowledgement was lost from effect never happened, it must retransmit. The receiver therefore must deduplicate, or else participate in a genuine atomic-commit protocol [6].

That is why the design does not remove deduplication. It relocates it. The producer half becomes a small local primitive. The remaining trade-offs are ordinary: one writer per entity creates a throughput ceiling, ordering is per source rather than global, and cross-entity atomicity still needs a saga or a true commit protocol.

## Conclusion

Effectively-once processing is not a network primitive. It is a composition of local atomicity, retry, and exact duplicate suppression. A single-writer entity with colocated transactional state can implement the producer half directly, leaving only one explicit duplicate boundary at the receiver. The reward is not magic exactly-once delivery. It is a smaller and more legible place to enforce the only duplicates that a distributed system cannot prevent.

## References

1. M. Kleppmann. Designing Data-Intensive Applications. O'Reilly, 2017, chapters 11-12.
2. C. Richardson. Microservices Patterns. Manning, 2018.
3. Debezium documentation. Outbox Event Router. Accessed 2026-07-18. https://debezium.io/documentation/reference/transformations/outbox-event-router.html
4. E. N. Elnozahy, L. Alvisi, Y.-M. Wang, D. B. Johnson. A Survey of Rollback-Recovery Protocols in Message-Passing Systems. ACM Computing Surveys 34(3), 2002.
5. P. Carbone, S. Ewen, G. Fóra, S. Haridi, S. Richter, K. Tzoumas. State Management in Apache Flink. VLDB, 2017.
6. J. Gray, A. Reuter. Transaction Processing: Concepts and Techniques. Morgan Kaufmann, 1992.
