Implement If-Match Precondition Update in Python

A mock resource store that uses the If-Match header's ETag to guard updates, preventing overwrites from stale clients.

Medium Python 3.9+ Aug 9, 2026 API design & gRPC 13 views 0 copies

Python code

51 lines
Python 3.9+
from dataclasses import dataclass
from typing import Optional


@dataclass
class Resource:
    id: str
    version: int = 1
    data: str = ""
    etag: str = "etag-1"


class MockResourceStore:
    def __init__(self):
        self.resources = {}

    def update(self, resource_id: str, new_data: str, if_match: Optional[str] = None) -> bool:
        resource = self.resources.get(resource_id)
        if not resource:
            return False

        if if_match and if_match != resource.etag:
            return False

        resource.data = new_data
        resource.version += 1
        resource.etag = f"etag-{resource.version}"
        return True


def main():
    store = MockResourceStore()
    store.resources["item-1"] = Resource(id="item-1")

    # Successful update with matching precondition
    success = store.update("item-1", "new data", if_match="etag-1")
    print(f"Success with matching etag: {success}")

    # Failed update with stale etag
    stale = store.update("item-1", "other data", if_match="etag-1")
    print(f"Success with stale etag: {stale}")

    # Correct new etag works
    correct = store.update("item-1", "latest data", if_match="etag-2")
    print(f"Success with current etag: {correct}")

    print(f"Final resource: {store.resources['item-1']}")


if __name__ == "__main__":
    main()

Output

stdout
Success with matching etag: True
Success with stale etag: False
Success with current etag: True
Final resource: Resource(id='item-1', version=3, data='latest data', etag='etag-3')

How it works

The MockResourceStore.update method mimics HTTP If-Match semantics: it proceeds only when the client's ETag matches the current stored ETag. The Resource dataclass tracks a version counter that increments on every successful update, and the ETag derives from it, ensuring each write produces a fresh token. When if_match is provided but stale or missing, the update is rejected with a False return, analogous to a 412 Precondition Failed response without raising an exception. The pattern prevents lost-update problems in concurrent systems by making optimistic concurrency explicit.

Common mistakes

  • Returning `True` on failed precondition instead of `False`
  • Not updating the ETag after a successful update
  • Ignoring the `if_match` parameter when it's `None`

Variations

  1. Raise a custom `PreconditionFailedError` instead of returning a boolean
  2. Store the ETag as a hash of the data field for additional integrity checking

Real-world use cases

  • RESTful API endpoints use If-Match headers with ETags to prevent concurrent overwrites of a resource.
  • Distributed caches validate version tokens before writing to avoid stale updates from replicated clients.
  • Document editors send the last-seen revision ID to the server to merge changes safely under concurrency.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.