Skip to content

Archive

APIs

14 articles
Software Engineering 22 Sep 2026 6 min read

Idempotency Keys Turn Retries into One Logical Operation

Idempotency Keys Turn Retries into One Logical Operation A client can lose the response to a successful request. The server may commit a charge, create an order, or enqueue a job, then the connection can fail before the response reaches the caller. From the client’s view, success and failure are now ambiguous. Retrying is necessary for availability, but an ordinary retry can repeat the side effect. An idempotency key gives the client a way to say that several HTTP attempts represent one logical operation.

Software Engineering 21 Sep 2026 7 min read

Idempotency Keys Make Retried Mutations Safe

Idempotency Keys Make Retried Mutations Safe A client can lose the result of a successful mutation without losing the mutation itself. The server may commit a payment, reservation, or job submission and then drop the connection before the response reaches the caller. From the client’s perspective, a timeout leaves two plausible states: the operation failed before commit, or it committed and only the response was lost. Blindly retrying a non-idempotent mutation can apply the effect twice. Refusing every retry leaves the caller unable to recover from an ambiguous outcome. An idempotency key gives both sides a stable identity for one logical operation, so a repeated attempt can reuse the result of the first accepted attempt instead of creating another effect.

Software Engineering 21 Sep 2026 6 min read

Idempotency Keys Bound Duplicate Mutations Across Retries

Idempotency Keys Bound Duplicate Mutations Across Retries A client can lose the response to a successful mutation. The server may commit a payment, reservation, or job submission and then lose the connection before the response reaches the caller. From the client side, timeout does not reveal whether the mutation failed before commit or succeeded before the response disappeared. A retry is necessary for availability, but a blind retry can repeat the side effect. An idempotency key gives both attempts a stable identity so the server can treat them as one logical operation.

Software Engineering 20 Sep 2026 7 min read

Idempotency Keys Make Retried Writes Safe to Repeat

Idempotency Keys Make Retried Writes Safe to Repeat A client can lose the response to a successful write. The connection may close after the server commits a payment, creates an order, or schedules a job but before the response reaches the caller. From the client’s perspective, failure and success can look identical. Retrying blindly is dangerous for operations with non-idempotent effects. Sending the same POST twice may create two resources or charge twice. Refusing to retry leaves the caller with an ambiguous outcome.

Software Engineering 19 Sep 2026 6 min read

Idempotency Keys Bound Retry Safety to a Request Identity

A client can send the same logical operation more than once even when it intended one effect. A timeout after POST /payments leaves an ambiguous boundary: the server may have committed the payment while the client received no response. Retrying restores delivery, but an ordinary retry can create a second payment. An idempotency key changes the interface by giving repeated attempts a stable request identity. The key is not a substitute for transactionality, and it does not make every operation intrinsically idempotent. It creates a protocol between client and server: attempts carrying the same key are treated as candidates for the same logical operation. The server still needs rules for request equivalence, concurrent arrival, persistence lifetime, failure recovery, and response replay.

Software Engineering 19 Sep 2026 7 min read

Deadline Propagation Bounds Request Lifetime Across Service Calls

A request can stop being useful before every process handling it stops working. An HTTP client may give up after two seconds while an upstream service continues a database query, an RPC, and a retry sequence for several more seconds. Those operations still consume connections, CPU time, queue capacity, and downstream concurrency even though their result no longer has a recipient. A deadline makes that usefulness boundary explicit. Propagating it through nested calls gives participating components a common upper bound derived from the original request. This differs from assigning an independent timeout at every hop: local timeouts limit individual operations, while a propagated deadline limits the lifetime of the operation graph.

Software Engineering 16 Sep 2026 7 min read

If-Match Turns Stale HTTP Writes Into Precondition Failures

Two clients can read the same HTTP resource, compute different replacements, and send those replacements minutes apart. If the origin accepts both writes without a precondition, the later request can overwrite the earlier result even though it was computed from stale state. HTTP provides a protocol-level guard for this case. A client can retain an entity tag from the representation it read and send that tag in If-Match with a later state-changing request. The origin evaluates the precondition before applying the method. If no listed tag strongly matches the current selected representation, the method is not performed because of that precondition.

Software Engineering 15 Sep 2026 7 min read

Idempotency Keys Bind Retries to One Logical Operation

A client can transmit a state-changing request, lose the response, and retry without knowing whether the first attempt committed. At that boundary, transport failure has created ambiguity rather than proof of application failure. Repeating the mutation blindly can create a second logical effect. An idempotency key gives the server a stable operation identity across those delivery attempts. The first accepted request associates the key with an operation record. A later request carrying the same key can then reuse the recorded outcome instead of executing the mutation again.

Software Engineering 13 Sep 2026 7 min read

Keyset Pagination Under Concurrent Writes

Keyset Pagination Under Concurrent Writes A query returns twenty rows ordered by creation time. Before the client asks for the next twenty, another transaction inserts a row near the front of that order. The data set has changed, but the client still expects page two to continue from the point page one reached. That expectation exposes the main difference between offset pagination and keyset pagination. An offset identifies a position in a particular query result. A keyset cursor identifies an ordering boundary. Under concurrent writes, those are not equivalent references.

Software Engineering 11 Sep 2026 8 min read

Consumer-Driven Contract Tests for Service Compatibility

Consumer-Driven Contract Tests for Service Compatibility Two services can pass their own test suites and still fail when deployed together. A provider may rename a field, narrow an accepted value, change a status code, or remove an endpoint. Its internal tests can remain green because those tests describe the provider’s own view of correct behavior. A consumer can still depend on the old interaction. Consumer-driven contract testing turns selected consumer expectations into executable contracts. The consumer records the interactions it requires. The provider then verifies those contracts against its implementation.

Software Engineering 02 Sep 2026 9 min read

Preventing Lost Updates with HTTP ETags and Conditional Requests

Two clients can read the same resource, make different edits, and then save them seconds apart. Without a concurrency check, the later write can silently replace the earlier one. This is the lost update problem. HTTP already provides a protocol-level mechanism for avoiding that failure: validators such as entity tags (ETags) combined with conditional request headers. Used correctly, they let a client say, “apply this change only if the resource is still the version I read.”

Web Development 02 Sep 2026 5 min read

HTTP Range Requests for Efficient Partial Downloads

HTTP range requests let a client ask for only part of a representation instead of downloading the entire body. They are useful for resumable downloads, media seeking, large files, and clients that need a known byte segment. The core mechanism is simple, but correct servers need to distinguish valid ranges, unsatisfiable ranges, validators, and ordinary full responses. A client requests a byte range A request can include: Range: bytes=1000-1999 If the server supports the request and the selected representation is 8,000 bytes long, it can respond:

Web Development 02 Sep 2026 5 min read

HTTP Content Negotiation and Correct Vary Headers

One URL can sometimes represent the same resource in several formats. An API might return JSON or CSV, while a documentation endpoint might return HTML or plain text. HTTP content negotiation lets a client express which representation it can accept. The server chooses a response and tells caches which request headers influenced that choice. The second part is easy to miss: if the response changes based on a request header, shared caches need the correct Vary metadata.

Software Engineering 01 Sep 2026 4 min read

Contract Tests for Reliable Service Boundaries

Distributed systems fail in an awkward place: each service can pass its own tests while the interaction between two services is incompatible. A provider may rename a JSON field, tighten validation, change an enum, or stop returning a value that a consumer quietly depends on. Contract tests make those cross-service assumptions executable. What a contract is A contract describes an observable interaction between a consumer and a provider. For an HTTP API, it might specify: