BTP CPI iFlows Part 7: Idempotency, Duplicate Detection and Exactly-Once Design
Prevent duplicate postings when messages are retried or resent: stable business keys, the Idempotent Process Call step, receiver-side duplicate checks, handling timeouts where the receiver already created data, and designing for "at least once" delivery with effectively-once outcomes.
Explanation
📌 KEY POINTS
✅ Retries mean "at least once" delivery — duplicates must be prevented by design.
✅ Use a stable business key (e.g. order number), not a technical message ID regenerated per retry.
✅ Idempotent Process Call skips processing if the key was already processed successfully.
✅ Receivers should also check duplicates (e.g. external reference) where possible.
⚠️ A timeout after the receiver created a document leads to retries that create duplicates unless the receiver is idempotent.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 6 covered retries. Now duplicate safety.
━━━━━━━━━━━━━━━━━━━━
▶ 1. DELIVERY SEMANTICS
- At most once, at least once, effectively once.
━━━━━━━━━━━━━━━━━━━━
▶ 2. BUSINESS KEYS
- Stable across resends.
━━━━━━━━━━━━━━━━━━━━
▶ 3. IDEMPOTENT PROCESS CALL
- Key expression; stored processed keys.
━━━━━━━━━━━━━━━━━━━━
▶ 4. RECEIVER-SIDE CHECKS
- External reference lookup before create.
━━━━━━━━━━━━━━━━━━━━
▶ 5. TIMEOUT CASES
- Check-then-create; reconciliation.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Add an idempotent process call keyed on order number.
- Resend the same order.
- Simulate a timeout after create and test receiver-side check.
✅ CHECKPOINT: one order created regardless of retries.
Code example
===== IDEMPOTENT PROCESS CALL =====Message ID (key): ${property.p_orderNumber} // stable business keySkip processing for duplicates ✔ → local process "CreateOrder" ===== CHECK-THEN-CREATE (receiver side) =====GET A_SalesOrder?$filter=PurchaseOrderByCustomer eq '${property.p_orderNumber}'if found → return existing | else → POST createReal project scenario
A sender generated a new message ID on each retry, so the idempotency check never matched and duplicates appeared. Switching the key to the purchase order number and adding a receiver-side lookup stopped duplicates.
Common mistakes
- Technical IDs as keys.
- No receiver checks.
- Ignoring timeout-after-create.
- Unlimited retries.
- No reconciliation.
Best practices
- Business keys.
- Idempotent process call.
- Receiver duplicate checks.
- Check-then-create.
- Periodic reconciliation.
Interview angle
Questions: "What is idempotency?", "How does the idempotent process call work?", "How do you handle timeout after create?"
Strong answer: semantics, keys, step, receiver checks, timeout handling.
Practice this lesson
Quick check
1. A supplier API timed out after creating an order; the retry created a duplicate. What design prevents this?
2. Which delivery semantic results from retries in asynchronous integrations?
3. A sender generates a new message ID on each retry and duplicates appear despite an idempotency step. What fixes it?
Interview questions
1. Suppose you inherit an existing CPI iFlows solution. How would you review it before making a change?
Answer it in your own words first, then compare.
2. Retries in your integrations create duplicate orders. How do you design for exactly-once outcomes?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- BTP CPI iFlows Part 1: What an iFlow Is — Message Model and Building Blocks
- BTP CPI iFlows Part 2: Adapters, Mapping and Message Processing Steps
- BTP CPI iFlows Part 3: Exception Handling and Error Subprocesses
- BTP CPI iFlows Part 4: Message Mapping — Graphical, XSLT or Groovy
- BTP CPI iFlows Part 5: Router, Splitter, Gather, Multicast and Aggregator Patterns
- BTP CPI iFlows Part 6: JMS Queues, Data Store and Asynchronous Retry Patterns
- BTP CPI iFlows Part 8: Performance Tuning — Payload Size, Streaming and Groovy