Skip to main content

litestar_events

CI Coverage Documentation Status PyPI - Version PyPI - Python Version License - MIT GitHub Stars Latest Commit

Checked with mypy linting - Ruff OpenSSF Scorecard GitHub Tag

Downloads Downloads/Month Downloads/Week

Event Emitter Backends for Litestar.


Table of Contents

Installation

litestar_events is a library. Add it to your project as a dependency:

uv add litestar_events

Or with pip:

pip install litestar_events

Install the core package plus the extra for the backend(s) you want:

# RabbitMQ backend
pip install "litestar_events[rabbit]"

# Multiple backends at once
pip install "litestar_events[rabbit,redis,nats]"

Using uv:

uv add "litestar_events[rabbit]"

Verify the installation

The package root is importable after installation:

>>> from litestar_events import __doc__
>>> isinstance(__doc__, str)
True

Backends

Backend Extra Client library
RabbitMQ rabbit aio-pika
Kafka kafka aiokafka
Kafka (C) confluent confluent-kafka
NATS nats nats-py
Redis redis redis (async)
MQTT mqtt aiomqtt
PostgreSQL postgres psycopg (LISTEN/NOTIFY)
AWS SQS sqs aiobotocore
GCP Pub/Sub pubsub gcloud-aio-pubsub
ZeroMQ zmq pyzmq (brokerless)

Quick start

The same Litestar app, three different transports. The app logic — your route handler, your listeners, your emitted events — is identical. Only the event_emitter_backend= line changes.

1. Define your event and listeners

# app.py
from __future__ import annotations

from typing import Any

from litestar import Request, post
from litestar.events import listener

USER_REGISTERED = "user_registered"


@listener(USER_REGISTERED)
async def send_welcome_email(*, email: str, **_: Any) -> None:
    print(f"[email] welcome to {email}")


@listener(USER_REGISTERED)
async def record_analytics(*, email: str, **_: Any) -> None:
    print(f"[analytics] new signup: {email}")


@post("/users")
async def register_user(request: Request, data: dict[str, str]) -> dict[str, str]:
    email = data["email"]
    request.app.emit(USER_REGISTERED, email=email)
    return {"status": "queued", "email": email}

Two listeners react concurrently to one event. Notice the listeners use **_: Any — that's the Litestar convention for keeping listener signatures forwards-compatible when multiple listeners share an event payload.

2. Pick a backend

Every backend constructor accepts listeners: Sequence[EventListener] plus its own keyword arguments. Use functools.partial to bake in the kwargs and hand the result to Litestar.

RabbitMQ (durable, at-least-once)

from functools import partial

from litestar import Litestar

from litestar_events.contrib.rabbit import RabbitEventEmitter

app = Litestar(
    route_handlers=[register_user],
    listeners=[send_welcome_email, record_analytics],
    event_emitter_backend=partial(
        RabbitEventEmitter,
        amqp_url="amqp://guest:guest@localhost/",
        # queue_name="my-app",   # set for work-queue semantics across replicas
    ),
)

Redis (fire-and-forget pub/sub)

from functools import partial

from litestar import Litestar

from litestar_events.contrib.redis import RedisEventEmitter

app = Litestar(
    route_handlers=[register_user],
    listeners=[send_welcome_email, record_analytics],
    event_emitter_backend=partial(
        RedisEventEmitter, redis_url="redis://localhost:6379/0"
    ),
)

PostgreSQL (LISTEN/NOTIFY)

from functools import partial

from litestar import Litestar

from litestar_events.contrib.postgres import PostgresEventEmitter

app = Litestar(
    route_handlers=[register_user],
    listeners=[send_welcome_email, record_analytics],
    event_emitter_backend=partial(
        PostgresEventEmitter, dsn="postgresql://postgres:postgres@localhost:5432/events"
    ),
)

AWS SQS (durable, at-least-once, managed)

from functools import partial

from litestar import Litestar

from litestar_events.contrib.sqs import SQSEventEmitter

app = Litestar(
    route_handlers=[register_user],
    listeners=[send_welcome_email, record_analytics],
    event_emitter_backend=partial(
        SQSEventEmitter,
        queue_name="litestar_events",
        region_name="eu-central-1",
        # credentials come from the standard boto chain (env, instance role, ...)
    ),
)

GCP Pub/Sub (durable, broadcast fanout)

from functools import partial

from litestar import Litestar

from litestar_events.contrib.pubsub import PubSubEventEmitter

app = Litestar(
    route_handlers=[register_user],
    listeners=[send_welcome_email, record_analytics],
    event_emitter_backend=partial(
        PubSubEventEmitter,
        project_id="my-gcp-project",
        topic_id="litestar_events",
        # subscription_name="my-app",  # set for work-queue across replicas
    ),
)

ZeroMQ (brokerless, fire-and-forget)

from functools import partial

from litestar import Litestar

from litestar_events.contrib.zmq import ZeroMQEventEmitter

app = Litestar(
    route_handlers=[register_user],
    listeners=[send_welcome_email, record_analytics],
    event_emitter_backend=partial(
        ZeroMQEventEmitter, pub_address="tcp://127.0.0.1:5557"
    ),
)

3. Trigger an event

curl -X POST http://localhost:8000/users \
    -H 'content-type: application/json' \
    -d '{"email": "ada@example.com"}'

Both listeners run concurrently for every emit, regardless of which backend you picked. The choice of backend changes how the event gets from emitter to listener (and what happens when things go wrong), not whether the listener fires.

Examples

Runnable examples for each backend live under examples/:

Delivery semantics

Different backends offer different guarantees. The library tries to give each backend the strongest reasonable default for its transport, while letting you weaken or tune those guarantees via constructor arguments:

  • RabbitMQ — at-least-once with per-listener error isolation and a dead-letter exchange for unparseable messages.
  • Kafka / Confluent — at-least-once with consumer-group offsets.
  • AWS SQS — at-least-once and durable; a message is deleted only after its listeners run. Instances sharing one queue are competing consumers (work-queue); broadcast fanout requires fronting the queue with SNS.
  • GCP Pub/Sub — at-least-once and durable. Each instance gets its own subscription by default (broadcast fanout); a shared subscription_name gives work-queue semantics.
  • ZeroMQ — fire-and-forget, at-most-once, brokerless. Events emitted before a subscriber finishes connecting are lost (no buffer, no persistence).
  • NATS — at-most-once by default; JetStream-backed at-least-once when configured.
  • Redis / MQTT / Postgres LISTEN/NOTIFY — fire-and-forget pub/sub; events emitted while no subscriber is connected are lost.

See each backend's docstring for the exact knobs.

Support ❤️

If you have any questions or need help, feel free to open an issue on the GitHub repository.

Motivation

Litestar ships with an in-process event emitter (SimpleEventEmitter) that runs listeners in the same process that emitted the event. That is great for side-effects that can tolerate "best-effort, same-process" delivery, but it falls short as soon as you need:

  • Cross-process fanout — multiple app instances reacting to the same event.
  • Durability — events that survive a worker crash or restart.
  • Backpressure / decoupling — producers that should not wait on slow listeners.

About

litestar_events provides drop-in BaseEventEmitterBackend implementations backed by common messaging systems, so you can keep Litestar's @listener ergonomics while swapping the transport underneath.

Author 🫅

This project is maintained by Hasan Sezer Taşan, It's me 👋

Analysis

Contributing ❤️

Any contributions are welcome! Please follow the Contributing Guidelines to contribute to this project.

Development 🧰

See the Contributing Guidelines for local setup, the common development tasks (exposed via mise), building and previewing the documentation, and the VS Code debugging configurations.

Releasing

Versioning and releases are automated with release-please, driven by Conventional Commit PR titles squash-merged into main. release-please maintains a release PR that bumps the version and CHANGELOG.md; merging it tags the release and publishes to PyPI. See the Contributing Guidelines for the commit conventions, and the Repository setup guide for one-time configuration and optional post-launch integrations such as a social preview, downstream packaging, and Repology.

Pause merges that change .github/workflows/, including Renovate action-pin updates, from merging a release PR until the entire Release run finishes. Workflow differences between the release commit and current main can block tag or release creation with a 403 when using GITHUB_TOKEN. See Release recovery for prevention and recovery steps.

For adoption or template-update reconciliation, ask your agent to "audit this template adoption/update against our existing project behavior". The shipped template-adoption skill also supports audits after an update was applied. It compares workflow behavior, required checks, custom tooling, and documentation, and asks before consequential cleanup. Its prek-workflow example shows why duplicate commands alone do not justify removing a workflow. Use the sibling repo-setup skill for repository settings and release setup.

Credits

This package was created with Copier and the hasansezertasan/copier-pyproject project template.

License 📜

This project is licensed under the MIT License.

Changelog 📝

For a detailed list of changes, please refer to the CHANGELOG.

Metadata

Release files for litestar-events 0.1.1

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

Source distribution (sdist)

Source distribution for litestar-events 0.1.1
File Size Uploaded Provenance
litestar_events-0.1.1.tar.gz 92.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for litestar-events 0.1.1
File Interpreter ABI Platform
litestar_events-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 153.3 kB

Release files / litestar_events-0.1.1.tar.gz

Download URL litestar_events-0.1.1.tar.gz
Size 92.0 kB
Tags Source
SHA-256 checksum
How to use checksums
90f53293c85352eabad460ec63119892c5a4a23c89a2109dc8c4e647386d8137
BLAKE2b-256 checksum
How to use checksums
e04c160eac767e53d0ce853305d0f0be8628245155fb9920d6b6eca7da6d6a71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / litestar_events-0.1.1-py3-none-any.whl

Download URL litestar_events-0.1.1-py3-none-any.whl
Size 61.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c94a710a18fba8596b0df7cd3fbf6ca698243cc3c31ad359dad75a93425dac4a
BLAKE2b-256 checksum
How to use checksums
c18335cf26f493fcaefca668e0e060b453f3962c0901d39a3e74f7f2c1cfe59e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Security for litestar-events 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for litestar_events-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

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