AR6: Reliability across services: deadlines, retries, idempotency, outboxes and contracts
Contracts and versions
🎯You'll be able to
Write a contract between services, check it with contract tests, and change it safely with versions.
🏠The everyday picture
A tiffin service's printed menu card is a promise: these dishes, these prices, these hours. Customers plan around it. Changing it without notice upsets people; printing a new card for next month doesn't.
📘What it really is
-
A contract says what a service accepts and returns: paths, required headers, body fields, response codes and their bodies. In the kit:
contracts/notify-v1.json. -
Clear errors are part of it: 400 for a malformed request, 422 for a well-formed request the service can't act on (an unknown template), each with an
errorexplaining why. -
Contract tests check the service keeps its promises, and that callers use it as described, without starting the whole system.
-
Safe changes add optional fields or new endpoints. Breaking changes (removing a field, changing a meaning) need a new version (
/v2/...), with the old one kept until callers have moved. -
Health checks (
GET /health) let deploy tools and monitors see whether a service can work.
📝A worked example
Input: a request to make the notify service accept email addresses as well as phones.
Steps:
- Safe option: add an optional
to.email; requests with onlyto.phonework as before. - Breaking option: rename
to.phonetoto.mobile. That breaks every caller. - If it must happen, publish
v2besidev1, move callers, then retirev1with a date. - Add contract tests for the new field and keep the old ones.
Expected output: a change that adds without breaking, or a new version with a plan for the old one.
🌍Where it's used
- Public APIs (payment gateways, maps) version their APIs and publish dates for retiring old versions.
- Teams with many services run contract tests in each build.
- OpenAPI files describe REST contracts in a standard format.
📝Case scenario
A delivery platform renamed eta to estimatedArrival in its tracking API "to be clearer". Restaurant apps still reading eta showed
blank times for a day. Adding the new field beside the old one, and removing eta months later in a new version, would have broken
nobody.
🖱️Try it
Read contracts/notify-v1.json and list one change that would be safe and one that would need v2. Success: you explain why each is safe
or breaking for an existing caller.
⚠️Common mistakes
- Vague errors. Sign: 500 with no explanation for a bad phone number. Fix: 400 or 422 with a clear
error. - Breaking changes in place. Sign: callers break after a deploy. Fix: add, or version.
- Contracts only in people's heads. Sign: "ask the team what it returns". Fix: a contract file and contract tests.
🛠️For your project
Project 2's tests 1 and 2 check the notify service against contracts/notify-v1.json: health, 202, 400 and 422 with error.
✅Quick check
What is the difference between a 400 and a 422 in the kit's contract?
Show the answer
400 is a malformed request; 422 is a well-formed one the service can't act on, such as an unknown template.
How do you make a breaking change to a contract safely?
Show the answer
Publish a new version beside the old one, move callers, then retire the old one with notice.
