Most integration diagrams draw a clean arrow from one system to another. Production behaves more like a negotiation between partial failures: the source commits, the network times out, the receiver succeeds, and the response disappears. If the design treats that sequence as an exception, retries will eventually create a duplicate or a human will reconstruct state from logs.

01

The real problem is not transport. It is preserving intent.

Suppose a CAP service accepts an order and an S/4HANA API must receive it. Calling the destination inside the original HTTP request looks simple, but it couples the local business transaction to remote latency and availability. If the remote call fails before the local commit, the user waits. If the local commit succeeds and the remote response is lost, the source cannot know whether retrying is safe.

The requirement should therefore be written as an invariant: once the source accepts an order, the intent to deliver it must survive process, network, and destination failures without creating the same business effect twice.

“Exactly once” is rarely a transport feature. What matters is one durable intent plus idempotent handling of repeated delivery.

02

Commit the business change and delivery intent together.

A transactional outbox moves the unreliable work outside the request while keeping the decision atomic. The source transaction updates business state and inserts an immutable delivery record. A separate publisher sends committed records to the messaging boundary. The request no longer waits for the destination, and a publisher crash does not erase the accepted order.

Fiori / APIsubmitOrder
CAP + HANAstock + outbox
one transaction
Messagingdurable handoff
Integration flowvalidate + map
S/4HANA APIidempotent effect
Logical delivery boundary. The exact adapter remains a deployment decision; durable handoff is the invariant.

Three details keep this pattern honest:

  • The outbox record is written in the same database transaction as the business change.
  • The publisher marks it delivered only after the messaging boundary acknowledges it.
  • The original payload and identifiers survive every retry and operator replay.
{
  "eventId": "8f359e80-84c8-4e43-9ba1-e4462eb32255",
  "eventType": "book.order.accepted",
  "schemaVersion": 1,
  "correlationId": "request-or-trace-id",
  "idempotencyKey": "order:8f359e80:s4-create",
  "order": { "bookId": 201, "quantity": 2 }
}

The event deliberately excludes user identity unless the receiver has a documented need and retention policy. An integration contract should carry the minimum data needed to perform the business effect, not a copy of the source system.

03

Give the business effect a stable identity before adding retries.

The transport should be treated as at-least-once. Duplicate delivery is normal: an acknowledgement may be lost, a consumer may restart after committing, or an operator may replay a quarantined message. The receiver must therefore remember successful idempotencyKey values and return the original outcome when the same intent arrives again.

The idempotency key identifies the intended receiver-side effect—not an HTTP attempt. Generating a new key during each retry defeats the mechanism. A stable eventId identifies the immutable fact; a stable idempotencyKey identifies what the receiver should do once.

If the destination cannot enforce idempotency, the integration boundary needs a durable lookup before the design can claim safe retries. That is less elegant than destination-side support, but it is still better than hoping duplicates are rare.

04

Retry policies need a failure taxonomy.

“Retry three times” is not an error strategy. A closed accounting period will not open because the same payload arrived again, while a temporary 503 may recover in seconds. The flow should classify failures before choosing an action.

Failure classExamplesPolicy
Business / terminalInvalid material, rejected stateDo not blind-retry. Route a safe reason code for business action.
AuthenticationExpired credential, missing scopeStop, alert, and correct the credential without leaking it into logs.
Transient transportTimeout, 429, temporary 5xxBounded exponential backoff with jitter; honor Retry-After.
Contract / mappingUnknown version, missing fieldQuarantine the original message and replay only after correction.

Once the retry budget is exhausted, the event belongs in a durable error path. Reprocessing must use the original identifiers, record who or what initiated the replay, and remain visible to operations.

05

Make recovery observable without exposing secrets.

An operator should be able to answer three questions without reading raw application logs: what was accepted, where delivery stopped, and whether replay is safe. That requires a small, consistent telemetry contract across the source, messaging layer, integration flow, and receiver.

  • Log eventId, correlationId, schema version, flow step, attempt count, outcome, and a safe error category.
  • Measure accepted, delivered, retried, quarantined, and oldest-undelivered events.
  • Alert on sustained failure and outbox age, not on a single transient retry.
  • Never log access tokens, authorization headers, complete remote error bodies, or unnecessary personal data.

Credentials should come from a destination or service binding using the strongest authentication supported by the target. The integration identity gets only the scopes and operations it needs. Rotation must not require a code release.

06

Architecture becomes a guarantee only after adversarial tests.

A diagram cannot prove that the outbox is atomic or that replay is safe. Before calling this design production-ready, I would require evidence for each failure boundary:

  1. A commit/rollback test proves the stock update and outbox record are atomic.
  2. A duplicate-delivery test proves one destination-side business effect.
  3. Retry tests cover timeout, 429 with Retry-After, and temporary 5xx responses.
  4. Contract tests reject unsupported versions while preserving the quarantined payload.
  5. A trace review follows one correlationId end to end.
  6. A replay test preserves the original idempotency key and records the actor and reason.

The practical goal is not a system that never fails. It is a system whose failures are bounded, explainable, and recoverable without creating a second business effect.