Practice interviews

Should you retry the timed-out webhook?

The receiver may have committed the update before the sender timed out.

The question

A dispatch status update crosses an ingress, an API service and a receiver client. Each layer currently permits three total attempts. A receiver applies status updates and bills once per accepted delivery.

Invented Observed sequence
  • 10:00:00 senderOperation delivery-731 requests status delivered for parcel P-52.
  • 10:00:01 receiver logdelivery-731 committed; billing entry B-91 created.
  • 10:00:03 senderNo acknowledgement received. The HTTP request timed out.
  • 10:00:04 draft designRetry with a new delivery identifier to avoid a duplicate-key error.
Current independent retry limits
Total attempts per incoming call
Ingress3
API service3
Receiver client3

Includes the first attempt at each layer. For this exercise every failed call is retried up to the stated total.

Contract

Repeated attempts for the same logical update must not create a second bill. Persist operation identity with the result. Keep deduplication evidence through the documented seven-day redelivery window.

“Specify the operation identity, retry owner, deadline and recovery readback.”

A strong answer, step by step

Open each step in turn. This is one strong answer, not the only one.

Step 1: Separate outcome from reply

What would you do here? Open the move you’d make.

  • Keep delivery-731 as the operation key across attempts.

    The strong move. The receiver can recognize the logical operation and return its saved result.

  • Create a new delivery ID for each transport attempt.

    Tempting, but it misses something. That converts a retry into a distinct billable operation.

See how a strong candidate says it

“The timeout says the sender lacks a reply. The receiver log indicates a committed update.”

What a strong candidate could say

Why it works: A repeated request needs the same logical operation identity, not a new billable event.

Step 2: Commit identity with the effect

What would you do here? Open the move you’d make.

  • Check a local cache before writing the bill.

    Tempting, but it misses something. Two receivers can both pass the check; a restart loses it.

  • Make duplicate admission part of the persistent effect boundary.

    The strong move. Concurrent delivery and crash recovery then share one operation record.

See how a strong candidate says it

“Atomically store delivery-731, the status change and its result, or use a transactional outbox with owned reconciliation.”

What a strong candidate could say

Why it works: A separate in-memory duplicate check can disappear on a crash or race with another attempt.

Step 3: Bound the multiplication

What would you do here? Open the move you’d make.

  • Give one layer the total deadline and bounded retry budget.

    The strong move. The other layers propagate the outcome and do not multiply attempts.

  • Keep three attempts at every layer and add a longer sleep.

    Tempting, but it misses something. Spacing changes timing, not the maximum multiplication.

See how a strong candidate says it

“Three total attempts at three independent layers permit up to 27 receiver calls for one logical request.”

What a strong candidate could say

Why it works: One retry owner with three total attempts permits at most three calls in this simplified chain.

Step 4: Reconcile before replaying

What would you do here? Open the move you’d make.

  • Call the transport exactly once and claim the problem is solved.

    Tempting, but it misses something. A sender can still lose a reply after a commit; transport alone does not establish one business effect.

  • Return the saved operation outcome and test concurrent duplicate delivery.

    The strong move. This proves the business effect boundary, including lost replies.

See how a strong candidate says it

“Read back delivery-731 and return B-91 if it committed. Retain the key for the seven-day redelivery window.”

What a strong candidate could say

Why it works: A request older than the deduplication window needs explicit reconciliation, not blind new identity.

The answer, in short

Decision
Retry only the same logical operation through one bounded retry owner.
Because
The persistent result protects the billable effect while the sender resolves an uncertain reply.
What would change it
If the receiver cannot admit a stable operation key, use readback or an owned reconciliation path before repeating the mutation.

Common traps

  • Confusing a timeout with proof of rollback.
  • Giving every layer an independent retry budget.

Check your answer

  • Did I identify one logical operation?
  • Does duplicate admission share the effect boundary?
  • Is the total attempt budget explicit?
  • Can I read back an uncertain commit?

Last reviewed Nov 10, 2026