Installation¶
Install faststream-outbox¶
Requirements¶
- Python 3.11+
- PostgreSQL 13+.
outbox_autovacuum_ddlsets the insert-triggered autovacuum options that 13 introduced; on 12 theALTER TABLEfails. CI runs the test suite on 13 and on 17. The examples use 17, so that is the safest choice if you're starting fresh. - A running Postgres instance accessible via SQLAlchemy
AsyncEngine
Free-threaded Python¶
faststream-outbox supports free-threaded (no-GIL) CPython. CI runs the full
test suite on the 3.14t and 3.15t interpreters, and a separate CI step asserts that
importing the outbox and its runtime dependencies keeps the GIL disabled. The
package is pure-Python
asyncio, so nothing in it depends on the GIL; installing on a python3.14t
interpreter resolves the free-threaded wheels of the compiled dependencies
(asyncpg, sqlalchemy, pydantic-core) automatically.
A dependency that has not declared free-thread safety re-enables the GIL
CPython re-enables the GIL process-wide when it imports an extension module
that has not declared itself free-thread-safe. The outbox's own runtime
dependencies are clear of this: SQLAlchemy declares safety as of 2.0.54,
which is the floor on 3.14 for that reason, and asyncpg and
pydantic-core never had the problem.
It still applies to any foreign-broker client you install for the
relay feature: if it hasn't declared free-thread safety
(for example aiokafka), importing it re-enables the GIL. The limitation
is in the client library; your outbox code still runs correctly.
The subscriber runs a single event loop by design, so free-threading does not add cross-core parallelism within one process. To use more cores, run more subscriber processes, the same scaling lever as on a GIL build.
Free-threaded wheels for the compiled dependencies currently exist for 3.14t
and 3.15t only (there are no cp313t wheels), so 3.13t is not a supported target.
Postgres¶
If you don't have a Postgres instance, you can start one with Docker:
docker run -d -p 5432:5432 \
-e POSTGRES_USER=outbox \
-e POSTGRES_PASSWORD=outbox \
-e POSTGRES_DB=outbox \
postgres:17
Optional extras¶
The base install ships only faststream + sqlalchemy[asyncio], with no
async Postgres driver, so you must install one (the asyncpg extra below,
or another async driver such as psycopg); the postgresql+asyncpg:// DSNs
in the examples need asyncpg specifically. Each optional extra unlocks one
feature; nothing else changes if you omit them.
| Extra | Install | What it enables |
|---|---|---|
asyncpg |
pip install 'faststream-outbox[asyncpg]' |
The asyncpg SQLAlchemy driver. Required to get LISTEN/NOTIFY short-circuit wakeups in the subscriber's fetch loop. With a different async driver (e.g. psycopg) but no asyncpg, the broker still works but the loop falls back to plain polling, which adds up to max_fetch_interval (default 10s) of idle latency between an INSERT and a dispatch; with no async driver at all the engine can't connect. |
fastapi |
pip install 'faststream-outbox[fastapi]' |
The faststream_outbox.fastapi.OutboxRouter. See FastAPI integration. |
validate |
pip install 'faststream-outbox[validate]' |
Alembic, for broker.validate_schema(). See Schema validation. Calling validate_schema() without this extra raises ImportError; every other code path works. |
prometheus |
pip install 'faststream-outbox[prometheus]' |
The PrometheusRecorder metrics adapter and native OutboxPrometheusMiddleware. See Observability. |
opentelemetry |
pip install 'faststream-outbox[opentelemetry]' |
The OpenTelemetryRecorder metrics adapter and native OutboxTelemetryMiddleware. See Observability. |
Combine extras with commas:
Or use the all extra to pull in every optional extra at once
(asyncpg, validate, fastapi, prometheus, opentelemetry):