Idempotency
Use an `Idempotency-Key` when the same create request might be retried. This prevents duplicate orders, payments, or conversions.
REST API Advanced
Advanced REST work starts when calls are high-volume, user money is involved, or multiple services depend on the same endpoint. At this level you design for duplicates, timeouts, abuse, and data consistency.
Use an `Idempotency-Key` when the same create request might be retried. This prevents duplicate orders, payments, or conversions.
Retry only safe failures such as timeouts or transient 5xx errors, and always back off instead of retrying instantly.
Protect shared infrastructure with per-key, per-IP, or per-user request limits.
Prevent lost updates with row version fields, timestamps, or optimistic locking.
Attach request ids, trace ids, latency, and error tags so teams can debug distributed systems quickly.
Sign webhook payloads with HMAC and verify the signature before trusting the event.
Choose REST, GraphQL, gRPC, async events, or streaming based on public compatibility, flexibility, and performance needs.
If a client times out, it may retry even though the server already created the record. Idempotency lets the server recognize that duplicate attempt and return the original result instead of creating a second row.
POST /api/orders
Idempotency-Key: order-20260325-00091
Content-Type: application/json
Authorization: Bearer TOKEN
{
"customer_id": 44,
"amount": 199.00,
"currency": "USD"
}
REST is request-response, but production systems often pair it with webhooks so downstream systems get updates as soon as something changes.
$payload = file_get_contents('php://input');
$incomingSignature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expectedSignature = hash_hmac('sha256', $payload, $sharedSecret);
if (!hash_equals($expectedSignature, $incomingSignature)) {
http_response_code(401);
exit('Invalid signature');
}
When multiple services call each other, a request id or trace id is what lets you connect the browser error to the backend logs, queue message, and database write.
{
"request_id": "req_74b2",
"trace_id": "trace_98ee",
"status": "error",
"error_code": "upstream_timeout",
"latency_ms": 1432
}
A fast REST endpoint can accept the request, validate it, store a job, and return immediately while background workers do the heavier processing.
High-read endpoints often sit behind CDN or Redis caching layers so the origin database is not hit for every dashboard load.
If the UI needs push updates instead of periodic fetch calls, REST usually handles CRUD while websockets or SSE handle live notifications.
Central place for auth, TLS termination, rate limits, routing, and policy enforcement.
Backend-for-Frontend keeps mobile, web, and partner clients from forcing one generic API shape.
Distributed workflows use local transactions plus compensating steps instead of one global transaction.
Moves mTLS, retries, telemetry, and traffic control into the proxy layer instead of every app.
| Style | Typical contract | Strength | Best fit |
|---|---|---|---|
| REST | OpenAPI plus HTTP semantics | Strong HTTP caching and public interoperability | Public APIs and broad platform support |
| GraphQL | Schema and client-selected operations | Harder to cache at the CDN edge | Client-driven data graphs |
| gRPC | Protobuf service definition | Usually internal and performance-oriented | Inter-service calls and streaming RPC |
A common production pattern is REST for commands and queries, then async events for propagation. Think `OrderCreated`, `PaymentCaptured`, or `ItemUpdated` flowing through queues or brokers.
Use SSE for simple server push over HTTP and WebSockets when you need full-duplex communication or bidirectional live interaction.
Public API products often combine docs, usage plans, API keys, quotas, billing, and self-serve portals. Developer experience becomes part of the product itself.