Skip to main content

API Design, Idempotency & Transactions

SECTION 1 — API DESIGN AS A LONG-TERM CONTRACT

At senior+ level, APIs are not implementation details.

They are:

  • contracts

  • promises

  • long-lived interfaces

  • externalized business rules

An API, once shipped, is almost impossible to take back.

Core Truth

APIs should change slower than internal code.

Elite backend engineers design APIs as if:

  • thousands of clients depend on them

  • some clients will never upgrade

  • clients will misuse them

Because that is reality.


SECTION 2 — THE API DESIGN HIERARCHY

Elite engineers design APIs in this order:

  1. Domain language

  2. Resources & boundaries

  3. Operations

  4. Validation rules

  5. Error contracts

  6. Versioning strategy

Average engineers start at step 4.


1️⃣ Domain-First Design

Before endpoints exist, define:

  • domain entities

  • invariants

  • transitions

  • forbidden states

Example:

“An application cannot be approved unless it is verified.”

This rule must live in one place — the backend.


2️⃣ Resource Boundaries

Good APIs expose nouns, not actions.

POST   /applications
GET /applications/{id}
POST /applications/{id}/submit
POST /applications/{id}/approve

Why this matters:

  • boundaries become clear

  • permissions become enforceable

  • workflows become explicit


SECTION 3 — IDENTITY, AUTH & TRUST BOUNDARIES

Backend engineers must answer two questions perfectly:

  1. Who is calling me?

  2. What are they allowed to do?

Anything less is insecurity.


Authentication ≠ Authorization

Authentication:

“Who are you?”

Authorization:

“What are you allowed to do?”

Never mix them.


Elite Rule

Authorization must be enforced in backend business logic, not in the frontend.

Frontend can assist — backend must enforce.


SECTION 4 — IDEMPOTENCY (NON-NEGOTIABLE)

Idempotency is mandatory for real backend systems.

Reality of Distributed Systems:

  • requests are retried

  • users double-click

  • gateways time out

  • mobile networks drop

If your backend cannot handle duplicate requests → it is broken.


Idempotency Definition

Repeating the same operation produces the same result.


Where Idempotency Is Required

  • payments

  • bookings

  • submissions

  • approvals

  • mutations with side effects


Standard Pattern (Production-Grade)

Idempotency-Key: uuid

Backend flow:

  1. Receive request

  2. Check idempotency store

  3. If exists → return stored response

  4. Else:

    • execute operation

    • store result

    • return response

This must be atomic.


Elite Insight

Idempotency is not a “feature”.

It is a correctness guarantee.


SECTION 5 — TRANSACTIONS AS REALITY BOUNDARIES

Transactions define when the world changes.

Anything outside a transaction is uncertain.


What Transactions Guarantee

  • atomicity

  • consistency

  • isolation

  • durability

But only if used correctly.


Common Anti-Patterns

❌ Long transactions

❌ External calls inside transactions

❌ Multiple unrelated responsibilities

❌ Hidden transactions via ORM magic


Elite Transaction Rule

Transactions should be small, short, and purposeful.

Inside a transaction:

  • validate state

  • enforce invariants

  • mutate data

  • commit

Nothing else.


SECTION 6 — DATA MODELING FOR CORRECTNESS

Backend engineers model truth, not convenience.


Good Data Models:

  • encode invariants

  • prevent invalid states

  • make illegal actions impossible

  • simplify business logic


Example: Status Columns

Bad:

status = "approved"

Better:

status ENUM('draft','submitted','verified','approved','rejected')

Even better:

  • separate state table

  • transition history

  • audit logs


Elite Rule

If invalid state is possible in DB, it will occur eventually.


SECTION 7 — SCHEMA EVOLUTION & MIGRATIONS

Production schemas never stop evolving.

Elite engineers plan for:

  • backward compatibility

  • rolling deploys

  • partial upgrades


Migration Rules

  1. Add before remove

  2. Make new fields nullable

  3. Backfill asynchronously

  4. Deploy code that handles both versions

  5. Remove old fields last

Violating these causes outages.


SECTION 8 — ERROR HANDLING AS PART OF DESIGN

Errors are not exceptions.

They are part of the contract.


Elite Error Design

  • structured

  • predictable

  • actionable

  • non-leaky

Example:

{
"error": {
"code": "INVALID_STATE",
"message": "Application must be verified before approval"
}
}

Never:

  • expose stack traces

  • expose DB errors

  • mix transport & business errors


SECTION 9 — TESTING FOR CORRECTNESS (NOT COVERAGE)

Elite backend tests focus on:

  • invariants

  • transitions

  • failure modes

  • retries

  • race conditions

Coverage is a side effect, not the goal.


Required Test Types

  • unit tests for domain logic

  • integration tests for workflows

  • idempotency tests

  • concurrency tests


SECTION 10 — BACKEND ENGINEER’S DAILY MINDSET

Top engineers ask:

  • What happens if this is retried?

  • What happens if this fails halfway?

  • What happens if two requests race?

  • What happens if the DB is slow?

  • What happens if state is stale?

If you don’t ask these, bugs will.


SECTION 11 — SIGNALS YOU’VE MASTERED THIS LAYER

You know you’re there when:

  • you naturally design idempotent APIs

  • you think in transactions & invariants

  • you trust backend logic over UI

  • you can reason about correctness under failure

  • you prevent bugs instead of fixing them