An API is a contract. Callers never see the code behind it.
So you can swap MySQL for PostgreSQL, split a monolith or add a cache. If the contract holds, no caller notices.
Is the JSON the contract?
Bad: Fields and types
Teams agree on every field yet disagree on meaning. Paise or rupees?
Good: Shapes plus promises
Semantics, guarantees, limits, auth, lifecycle. Most bugs hide in what nobody wrote down.
The API says 201 Created. Has any money moved?
No. The payment exists, but stays pending until the payer approves in their UPI app. The app polls, or waits for a webhook.
≈9×
faster: one screen-shaped call, not ten
Assume 80 ms per mobile round trip and 1 ms inside the data centre. Ten dependent calls from the phone: 800 ms. One call doing them server-side: 90 ms.
Your list never promised an order. It just came back newest first. Then you change it.
Hyrum’s Law
With enough users, someone depends on every observable behaviour. A caller skipped sorting; now it breaks.
Add an optional field: safe. Rename one: old apps break.
To an old client, a rename is a removal. It finds amount_paise missing and shows ₹0 or crashes. You can’t force it to upgrade.
Change a published API without breaking it
- Only add: optional fields, new endpoints
- Clients ignore fields they don’t recognise
- A true break gets /v2, run side by side
- Retire with Deprecation and Sunset headers, then brownouts
Remember
An API is a contract — operations, shapes, errors and promises like idempotency and limits — that hides the implementation. Change it only by adding, because callers depend on everything they can see.