helpyourneighbour/docs/adr/001-idempotency.md
OpenClaw b44e7bf46c
Some checks are pending
Docker Test / test (push) Waiting to run
fix(#24): Implement idempotency protection for critical write operations
2026-03-07 00:13:31 +00:00

2 KiB

ADR 001: Idempotency for Critical Write Operations

Status

Accepted

Context

Repeated requests (retries/double clicks) can currently create duplicate offers/acceptances. This is problematic because:

  • Users may accidentally double-click buttons
  • Network issues might cause requests to timeout and be retried
  • The system should behave deterministically when handling retries

Decision

We implement idempotency key handling for critical POST endpoints:

  1. Add x-idempotency-key header support to POST endpoints
  2. Store request results in a database table for replaying responses
  3. Return cached responses for identical keys
  4. Apply this to the most critical endpoints:
    • /offers/:requestId
    • /offers/negotiation/:offerId
    • /offers/accept/:offerId
    • /help-requests

Consequences

Positive

  • Eliminates duplicate offers/acceptances from retries
  • Makes critical endpoints behave deterministically on retries
  • Improves user experience by preventing accidental duplicates
  • Follows REST best practices for idempotent operations

Negative

  • Adds complexity to request handling
  • Requires database storage for idempotency keys
  • Slight performance overhead for idempotent requests

Implementation Details

Database Schema

Added idempotency_keys table with:

  • key: Unique identifier for the request (VARCHAR)
  • response_body: Cached response data (TEXT)
  • created_at: Timestamp of when the key was first used

Middleware

Created requireIdempotencyKey middleware that:

  1. Checks for x-idempotency-key header in POST requests
  2. If key exists, checks if it has been used before
  3. If used before, returns cached response
  4. If new, stores the request and caches the eventual response

Endpoints

Applied to critical write operations:

  • POST /offers/:requestId
  • POST /offers/negotiation/:offerId
  • POST /offers/accept/:offerId
  • POST /help-requests

Testing

Added tests for idempotency behavior in the existing test suite.