# 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.