Skip to main content

lapinbeam

CI Docs License: MIT

Real-time distributed systems framework for Python with a Rust core. An actor model inspired by Erlang/Elixir (BEAM), built with Rust (Tokio) exposed through PyO3.

Repository: https://github.com/rroblf01/lapinbeam · Docs: https://rroblf01.github.io/lapinbeam/ · Changelog

Status

Alpha. MVP: two-node bidirectional message passing over a multiplexed TCP transport.

Features

  • @actor decorated Python classes with async def receive(msg), or typed dispatch via @on(Type) / @on(default=True) (see below).
  • Supervisor with restart strategies (one_for_one).
  • Node with transparent remote actor references.
  • Multiplexed TCP transport (one socket per peer) with bincode serialization.
  • Heartbeat and connection watchdog in the Rust core.
  • Automatic reconnection of desired peers with backoff.
  • Type-preserving payloads: @dataclass and Pydantic v2 models round-trip between nodes via lapinbeam.codec.

Install

pip install lapinbeam

The wheel is built for abi3 >= 3.11, so a single artifact covers Python 3.11 through 3.14.

Quickstart (two nodes)

# terminal 1
NODE_NAME=node_a@127.0.0.1:9001 PEER=node_b@127.0.0.1:9002 uv run python examples/app_node_a.py
# terminal 2
NODE_NAME=node_b@127.0.0.1:9002 PEER=node_a@127.0.0.1:9001 uv run python examples/app_node_b.py

Or with Docker (validated end-to-end: 100/100 ACKs inside the compose network):

docker compose up --build

Typed message dispatch

By default an actor implements a single async def receive(self, msg). As an alternative, use @on(Type) to dispatch by the message's real type — which lapinbeam.codec already preserves for @dataclass/Pydantic payloads across nodes — and @on(default=True) for a catch-all handler:

from dataclasses import dataclass
from lapinbeam import actor, on


@dataclass
class Task:
    payload_id: int
    name: str


@actor(name="worker")
class Worker:
    @on(Task)
    async def handle_task(self, msg: Task):
        ...

    @on(default=True)
    async def handle_other(self, msg):
        print("unrecognized message:", msg)

An actor with any @on handler stops using receive entirely; a message whose type has no dedicated handler and no @on(default=True) fallback raises TypeError (crashing the actor, so Supervisor restarts it like any other unhandled exception). Actors that only define receive are unaffected.

Development

uv sync                       # create .venv, build the extension, install deps
uv run maturin develop        # fast rebuild of the Rust extension
uv run pytest                 # Python test suite
cargo test                    # Rust test suite
uv run python bench/bench_remote.py   # throughput benchmarks
uv run python bench/bench_latency.py  # RTT latency percentiles

Nothing is installed on the OS: everything lives in .venv.

Documentation

Full docs (English + Spanish) live under docs/ and build with MkDocs + Material:

uv sync --group docs           # installs mkdocs, mkdocs-material, mkdocs-static-i18n
uv run mkdocs serve             # http://127.0.0.1:8000, live-reloads on edits
uv run mkdocs build --strict    # static site in site/ (gitignored)

Each page has an English file (e.g. docs/getting-started.md) and its Spanish translation (docs/getting-started.es.md); mkdocs-static-i18n serves the Spanish build under /es/ with a language switcher.

Benchmark snapshot

Measured on this machine (Python 3.14, loopback):

Metric Result
asyncio.Queue put/get ~1.6M msg/s
lapinbeam local send ~1.2M msg/s
lapinbeam remote (loopback TCP) throughput ~16K msg/s
Local dispatch RTT p50 0.007 ms
Remote loopback TCP RTT (send + ack) p50 0.44 ms / p99 0.93 ms

Limitations

  • Payloads must be JSON-compatible (dict/list/str/int/float/bool/None). Ints are limited to i64/u64; larger ints raise TypeError.
  • __lb_type__ is a reserved payload key (used by the type-preserving codecs).
  • Type preservation happens only on remote sends; local sends pass the object by reference (zero-copy). Nested dataclass-in-Pydantic fields are not rebuilt.
  • Actor names must be unique per node. If two nodes dial each other at the same time, two connections are created (deduplication not implemented yet).
  • Payloads larger than 16 MiB are rejected on the sender.

Publishing to PyPI

uv build                      # produce wheel (abi3) + sdist in dist/
uv publish                    # upload to PyPI (uses UV_PUBLISH_TOKEN)

CI (./.github/workflows/ci.yml) runs the test matrix on Python 3.11-3.14, a Docker Compose end-to-end check, and builds the distributable artifacts.

Project layout

src/           Rust core (_core extension module)
lapinbeam/     Pure-Python layer (@actor, Node, Supervisor, refs)
tests/         Rust integration tests
tests-python/  Python tests (pytest)
examples/      Two-node bidirectional demo
bench/         Latency benchmarks

License

MIT

Release files for lapinbeam 0.1.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 lapinbeam 0.1.0
File Size Uploaded
lapinbeam-0.1.0.tar.gz 109.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lapinbeam 0.1.0
File Interpreter ABI Platform
lapinbeam-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details

Total release size: 817.8 kB

Release files / lapinbeam-0.1.0.tar.gz

Download URL lapinbeam-0.1.0.tar.gz
Size 109.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d6f962c41301982ba97847f101c9d3e72a439ad2ebe9f9e708ed0fdfdac3829d
BLAKE2b-256 checksum
How to use checksums
bad8b5cf67ffb821fffcc2263ea82e092262644fa47685d7a5d716f8d4bde652
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 Aug 16, 2026.

Transparency log

Release files / lapinbeam-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL lapinbeam-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 708.3 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
38be3832f4a9322c2c61e12eeab0be825d2be640276e5d993e0c1eb0b6a4d500
BLAKE2b-256 checksum
How to use checksums
081467cd6c430bdb261762bb917c59cf93d386cc3091a93ab5f42c1ed13ddb1d
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 Aug 16, 2026.

Transparency log

Release history Release notifications | RSS feed

1.3.0

5 release files

1.2.0

5 release files

1.0.3

5 release files

1.0.2

5 release files

1.0.1

5 release files

1.0.0

5 release files

This release

0.1.0 This release

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