Skip to main content

pactix

pactix is a Python library for transactional outbox and inbox workflows on PostgreSQL and MySQL 8, built on SQLAlchemy (async).

Use it when a service needs to commit business data and outgoing events in the same transaction, store incoming messages before handler execution, and retry failed work safely across multiple workers.

Features

  • PostgreSQL and MySQL 8 persistence, auto-detected per call from the SQLAlchemy engine/connection — no config knob
  • Deduplication by source + message_id on the inbox side
  • FIFO within the same event_type + ordering_key
  • Optional unordered inbox processing with a stale-event filter contract
  • Retry scheduling and lease-based recovery for stuck workers
  • Optional wakeup-driven outbox scheduling — post-commit signal and PostgreSQL LISTEN/NOTIFY with adaptive fallback polling (see Operations)
  • Transport-agnostic core protocols
  • Built-in helpers for common hooks, stale-event filters, and closure-based adapters
  • Optional Kafka adapters behind the kafka extra
  • Optional HTTP adapters behind the http extra

If a publisher or handler may run more than once, that is normal. Business effects still need idempotent application logic.

Installation

pip install "pactix[postgres]"     # core + asyncpg driver (PostgreSQL)
pip install "pactix[mysql]"        # core + asyncmy driver (MySQL 8)
pip install "pactix[kafka]"        # + Kafka transport (aiokafka)
pip install "pactix[http]"         # + HTTP transport (httpx + starlette)
pip install "pactix[migrations]"   # + Alembic for running the migrations

The core package ships no database driver — install one of the driver extras above (extras combine, e.g. pactix[postgres,kafka]).

Breaking change: asyncpg moved out of the core dependencies into the postgres extra. Existing PostgreSQL services must change their requirement from pactix to pactix[postgres] when upgrading — nothing else changes. The failure mode without it is loud: SQLAlchemy raises at engine creation naming the missing DBAPI.

MySQL 8 note: stock MySQL 8 authenticates with caching_sha2_password. Over a non-TLS connection asyncmy's RSA password exchange additionally needs the cryptography package, which the mysql extra already pulls in (TLS connections do not need it).

Database setup

pactix does not run migrations for you. Either run the bundled Alembic migrations (src/pactix/db/migrations, see alembic.ini) or copy the table definitions in pactix.db.tables into your own migration system. The library expects two tables: outbox_message and inbox_message.

The same migrations run on both dialects (the wakeup-trigger revision no-ops on MySQL); for MySQL run alembic upgrade with a sync mysql+pymysql:// URL. See Operations for the MySQL notes.

Documentation

See examples/worker_loop.py for a runnable worker-loop sketch.

Development

make install   # uv sync with all extras
make check     # format + lint + mypy + test

Database-backed tests use testcontainers and require Docker.

Metadata

Release files for pactix 0.2.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 pactix 0.2.0
File Size Uploaded
pactix-0.2.0.tar.gz 600.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pactix 0.2.0
File Interpreter ABI Platform
pactix-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 643.6 kB

Release files / pactix-0.2.0.tar.gz

Download URL pactix-0.2.0.tar.gz
Size 600.8 kB
Tags Source
SHA-256 checksum
How to use checksums
c04445c14b77ed492aa9336a4a405f4b3d6307c7d75ab0dd341442529b8d2223
BLAKE2b-256 checksum
How to use checksums
757003142371071f0f78a05ae48357835ce90670b43bd17dc89a446ad098c6bc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / pactix-0.2.0-py3-none-any.whl

Download URL pactix-0.2.0-py3-none-any.whl
Size 42.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e1cc2f200f24de5a14bb602946648818fca0ec30a73369083ec99b82fc75cc25
BLAKE2b-256 checksum
How to use checksums
e3171bf13952c2e34a5e52901da9926e28caacd94c5d985b49bd191a40b18e34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

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