Course contents
On this page
Retry a purchase without buying twice
Give an operation a stable identity and preserve its result across an uncertain response.
Sending a complete request does not guarantee that its reply arrives. Suppose the shop sends “buy product 27.” The database commits order 501, but the connection drops before the application sees the order number.
Trying again seems reasonable. Without additional information, however, the server sees another purchase and creates order 502. The problem is not that either transaction failed. It is that two successful transactions represented one intention.
Name the intention before sending it
The client creates a request identifier, R17, before its first attempt. It retains that identifier for retries of this purchase. A genuinely new purchase gets a new identifier.
Our teaching service stores a request record containing the authenticated caller, request identifier, relevant input, and result. The combination of caller and identifier is unique. Comparing the input prevents the same identifier from silently meaning two different purchases.
Inside one database transaction, the service checks or creates that request record, performs the purchase once, and stores the result. Concurrent attempts must be serialized for the same request key, for example through a unique constraint and appropriate transaction handling. A plain “check, then insert” outside such protection repeats the original race.
- First attempt: R17
Commit order 501 and the stored result for R17 together.
- The reply is lost
The client knows the request identifier but not the outcome.
- Retry: R17
Find the committed request record and return order 501.
If the transaction aborts before committing, neither the purchase nor its completed request record exists. A retry can attempt the operation again. If it commits, both exist. This depends on the atomic transaction mechanism already taught; saving the request record in an unrelated store does not automatically provide that property.
Decide how long a retry remains recognizable
Keeping a result forever consumes space. Deleting it too soon permits an old retry to look new. The protocol needs a documented retry lifetime and behavior for expired identifiers, with retention that supports that contract.
The guarantee also has a boundary. A transaction recording an order cannot undo an external charge or a physical shipment. Those steps need their own identity and recovery design, as in the outbox example.
Predict the changed request
R17 originally bought one item. A retry uses R17 but requests three. Should the service return a new three-item order?
Work through the identifier conflict
No. The same identifier must retain its original meaning. Reject the conflicting input rather than executing a different purchase or pretending the old result answers the new request. The caller must use a new identifier for a new intention.
We have made uncertain replies manageable under one transactional authority. Next, we need to understand uncertainty about whether that authority is still running.
Further study: MIT’s distributed-systems course and key/value-service labs. The request-record design above is a stated teaching contract, not a claim that every RPC framework supplies it.
Extended reference
The extended chapter preserves the original technical coverage, additional examples, and citations. The explanation above supplies the concepts needed for this page; the reference develops the specialist cases.
Find a section from the original chapter
- Learning outcomes
- The purchase that succeeded without a reply
- Framing turns a byte stream into messages
- Serialization is a physical and semantic choice
- RPC and HTTP expose different shapes of conversation
- A minimal idempotent transaction boundary
- Deadlines and timeouts
- Retries alter the workload
- Pooling, pipelining, and multiplexing
- Case connection: a mature wire protocol exposes state
- Parsing partial input is a state machine
- Duplicate suppression under simultaneous first attempts
- Retention is part of the idempotency guarantee
- Errors need scope and recovery rules
- Scenario: a retry that is correct but still expensive
- A lost-reply sequence preserves one business identity
- Design conclusion
- Sources and further reading