Skip to main content

idempotency-kit

Production-ready idempotency library for async Python applications.

PyPI Python License CI codecov Docs

Ensure operations execute exactly once, even when called multiple times with the same idempotency key. Built for production microservices with graceful degradation, collision handling, and observability.

[!TIP] Building this with an AI assistant? Hand it one page instead of the whole site: the complete API surface, the rules that break code when they are broken — what the key actually identifies, what two concurrent callers really do, how a TTL in seconds is rounded — the mistakes models make with this API, and a map of which page to fetch for the rest. Every docs page is also served as raw Markdown at its own URL, and a Copy page button at the top of each one hands it straight to a chat window.

Features

  • Clean Architecture — core domain separated from infrastructure
  • Protocol-Based — easy to swap storage backends (Redis, custom)
  • Type-Safe — full type hints with Pydantic validation
  • Async First — built for asyncio applications
  • Graceful Degradation — high availability over strict exactly-once
  • In-flight Reservation — a retry that arrives while the original is still running waits for its result or gets a 409; the action runs once
  • Request Fingerprints — name the parameters that identify a request, and a key reused for a different one is refused instead of replayed
  • Observability — built-in metrics (hits, misses, collisions, latency)
  • Bulk Operations — efficient get_many, save_many, delete_many
  • Redis Cluster Compatible — non-transactional pipelines
  • Decorator Pattern — @async_idempotent for zero-boilerplate integration

Installation

pip install idempotency-kit

# With Redis support (recommended)
pip install idempotency-kit[redis]

# With Dishka DI
pip install idempotency-kit[dishka,redis]

Requirements: Python 3.11+, Redis 6+

Quick start

from idempotency_kit import AsyncIdempotencyCoordinator, PydanticResultAdapter, async_idempotent

class CreateOrderUseCase:
    def __init__(self, uow: AsyncUnitOfWork, coordinator: AsyncIdempotencyCoordinator):
        self._uow = uow
        self.coordinator = coordinator

    @async_idempotent(
        operation="order.create",
        adapter=PydanticResultAdapter(OrderDTO),
    )
    async def execute(
        self,
        dto: CreateOrderDTO,
        idempotency_key: str | None = None,
    ) -> OrderDTO:
        """Create order - idempotency handled automatically."""
        async with self._uow.transaction() as tx:
            # Your business logic - no idempotency code needed!
            order = await tx.orders.create(dto.items, dto.total)
            await tx.outbox.create(OrderCreatedEvent(order_id=order.id))
            
            return OrderDTO.from_entity(order)

Pass idempotency_key to downstream services for distributed idempotency:

# Orchestrate multiple services with same key
await identity_service.create_user(..., idempotency_key=idempotency_key)
await payment_service.charge(..., idempotency_key=idempotency_key)

How it works

1. Client provides key

POST /api/orders
Idempotency-Key: abc-123-def

2. Server checks cache

cached = await repo.get("order.create", "abc-123-def")
if cached:
    return cached.result  # Return immediately ✅

3. Server executes (if not cached)

order = await create_order(dto)
await repo.save(record)  # Cache result for future requests
return order

4. Concurrent requests handled

If two requests arrive while the first is still executing:

  • First request: reserves the key → execute → write the result over the reservation ✅
  • Second request: finds the reservation → waits for the first result → return ✅ (or a 409 with in_flight="raise")

Both requests get the same result, and the business logic ran once.

Use cases

  • HTTP APIs — ensure POST/PUT requests are idempotent
  • Background Jobs — prevent duplicate processing on retries
  • Event Consumers — handle duplicate events gracefully
  • Message Queues — at-most-once message processing

Documentation

📚 Full Documentation

Development

make install          # uv sync --group dev
make check            # ruff + mypy
make test-unit        # unit tests (no Docker)
make test-integration # integration tests (Docker required)
make test             # all tests with coverage
make docs-serve       # local docs preview

See CONTRIBUTING.md for the full guide.

License

Apache 2.0

Metadata

Release files for idempotency-kit 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for idempotency-kit 0.4.0
File Size Uploaded
idempotency_kit-0.4.0.tar.gz 32.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for idempotency-kit 0.4.0
File Interpreter ABI Platform
idempotency_kit-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 75.5 kB

Release files / idempotency_kit-0.4.0.tar.gz

Download URL idempotency_kit-0.4.0.tar.gz
Size 32.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6e511c745d26d768e855f52d8de19289a14e625f2d6d0c93c39259a48941360d
BLAKE2b-256 checksum
How to use checksums
d43b7afd1e73923111fa10a8c57641e8a6aad004e2e495733aca30927ef2bcc4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / idempotency_kit-0.4.0-py3-none-any.whl

Download URL idempotency_kit-0.4.0-py3-none-any.whl
Size 43.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f3292b5d0c71841b98aeee1027b5ff048267e28ab6b16a8e374f111929bed91b
BLAKE2b-256 checksum
How to use checksums
125b2381ecfab32e96e3412bb5af8b7c1d7712b2d8599c345a1aa7ee231c7eef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.4.1

2 release files

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page