🧹 idemptx
A minimal, pluggable idempotency decorator for FastAPI, designed for payment and retry-safe APIs.
Supports Redis as backend for deduplication, distributed locking, and response caching.
✨ Features
- ✅ Supports
Idempotency-Keyheader out of the box - 🔒 Redis-backed lock to prevent double execution
- ⚡️ Sync & Async backends with auto-detection
- 🧠 Request signature validation (method + URL + headers + body)
- ⏳ Configurable
wait_timeoutbehavior - 🔁 Response replay from cache (with headers)
- 🔢 In-memory backend for testing/local use
📦 Installation
pip install idemptx
🚀 Quick Start
import redis
from fastapi import FastAPI, Request
from idemptx import idempotent
from idemptx.backend import RedisBackend
app = FastAPI()
client = redis.Redis(host='localhost', port=6379, db=0)
redis_backend = RedisBackend(client)
@app.post('/orders')
@idempotent(storage_backend=redis_backend)
async def create_order(request: Request):
return {'status': 'created'}
⚠️ You must include
request: Requestin your endpoint parameters!
🔧 Advanced Usage
@idempotent(
storage_backend=redis_backend,
key_ttl=60,
wait_timeout=3.0,
validate_signature=True,
)
key_ttl: How long to hold cache and lock (in seconds)wait_timeout: Wait for lock to be released (0 = immediate failure)validate_signature: Whether to compare request content on replays
🔀 Async Redis Backend
import redis.asyncio as aioredis
from idemptx.backend import AsyncRedisBackend
async_client = aioredis.Redis(host='localhost', port=6379, db=0)
async_backend = AsyncRedisBackend(async_client)
🔖 In-memory Backend (for testing only)
from idemptx.backend import InMemoryBackend
backend = InMemoryBackend()
@app.post('/example')
@idempotent(storage_backend=backend)
async def create_something(request: Request):
return {'ok': True}
Note: Not suitable for multi-process or production environments.
🔐 Response Headers
| Header | Description |
|---|---|
Idempotency-Key |
Echoed back to client |
X-Idempotency-Signature |
Hash of request for conflict detection |
X-Idempotency-Status |
"hit" or "new" |
❗️Limitations
Currently, only JSONResponse is supported for caching.
If your endpoint uses response_model, the return value is typically a Pydantic model, which FastAPI wraps after the decorator has executed. This means the idempotency decorator cannot cache the final serialized response or set headers reliably in this case.
To enable caching, please return a JSONResponse explicitly from your endpoint.
Support for response_model and automatic response wrapping may be added in a future version.
📄 License
MIT License © 2025 pypy-riley
Metadata
Release files for idemptx 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| idemptx-0.2.2.tar.gz | 8.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| idemptx-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.7 kB
Release files / idemptx-0.2.2.tar.gz
| Download URL | idemptx-0.2.2.tar.gz |
|---|---|
| Size | 8.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
03382df7c866f6ff0960708dd81a49b4d879f530b012596402a3056259fe3102
|
|
BLAKE2b-256 checksum How to use checksums |
3b77b12c4ff62381011ca9362c13ec4a833992e251d18bfc339cf00968c8606f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.2 CPython/3.12.2 Darwin/23.3.0
|
Release files / idemptx-0.2.2-py3-none-any.whl
| Download URL | idemptx-0.2.2-py3-none-any.whl |
|---|---|
| Size | 9.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dfe1c29f3e15b960b78923af12b18e15fb8eadb1670df37fa9aa14a47881b567
|
|
BLAKE2b-256 checksum How to use checksums |
fd8ff8588bdf7eb08159c036dc35c4eec283172cbe52379dcebd66d46e9d9d3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.2 CPython/3.12.2 Darwin/23.3.0
|