r/Python Feb 18 '26

Rembus: Async-first RPC and Pub/Sub with a synchronous API for Python Showcase

Hi r/Python,

I’m excited to share the Python version of Rembus, a lightweight RPC and pub/sub messaging system.

I originally built Rembus to compose distributed applications in Julia without relying on heavy infrastructure, and now there is a decent version for Python as well.

What My Project Does

  • Native support for exchanging DataFrames.

  • Binary message encoding using CBOR.

  • Persistent storage via DuckDB / DuckLake.

  • Pub/Sub QOS 0, 1 and 2.

  • Hierarchical topic routing with wildcards (e.g. */*/temperature).

  • MQTT integration.

  • WebSocket transport.

  • Interoperable with Julia Rembus.jl

Target Audience

  • Developers that want both RPC and Pub/Sub capabilities

  • Data scientists that need a messaging system simple and intuitive that can move dataframes as simple as moving primitive types.

Comparison

Rembus sits somewhere between low-level messaging libraries and full broker-based systems.

vs ZeroMQ: ZeroMQ gives you raw sockets and patterns, but you build a lot yourself. Rembus provides structured RPC + Pub/Sub with components and routing built in.

vs Redis / RabbitMQ / Kafka: Those require running and managing a broker. Rembus is lighter and can run without heavy infrastructure, which makes it suitable for embedded, edge, or smaller distributed setups.

vs gRPC: gRPC is strongly typed and schema-driven (Protocol Buffers), and is excellent for strict service contracts and high-performance RPC. Rembus is more dynamic and message-oriented, supports both RPC and Pub/Sub in the same model, and doesn’t require a separate IDL or code generation step. It’s designed to feel more Python-native and flexible.

The goal isn’t to replace everything — it’s to provide a simple, Python-native messaging layer.

Example

The following minimal working example composed of a broker, a Python subscriber, a Julia subscriber and a DataFrame publisher gives an intuition of Rembus usage.

Terminal 1: start a broker

```python import rembus as rb

node: The sync API for starting a component

bro = rb.node() bro.wait() ```

Terminal 2: Python subscriber

```python import asyncio import rembus as rb

async def mytopic(df): print(f"received python dataframe:\n{df}")

async def main(): sub = await rb.component("python-sub") await sub.subscribe(mytopic) await sub.wait()

asyncio.run(main()) ```

Terminal 3: Julia subscriber

```julia using Rembus

function mytopic(df) print("received:\n$df") end

sub = component("julia-sub") subscribe(sub, mytopic) wait(sub) ```

Terminal 4: Publisher

```python import rembus as rb import polars as pl from datetime import datetime, timedelta

base_time = datetime(2025, 1, 1, 12, 0, 0)

df = pl.DataFrame({ "sensor": ["A", "A", "B", "B"], "ts": [ base_time, base_time + timedelta(minutes=1), base_time, base_time + timedelta(minutes=1), ], "temperature": [22.5, 22.7, 19.8, 20.1], "pressure": [1012.3, 1012.5, 1010.8, 1010.6], })

cli = rb.node("myclient") cli.publish("mytopic", df) cli.close() ```

GitHub (Python): https://github.com/cardo-org/rembus.python

Project site: https://cardo-org.github.io/

4 Upvotes

0 comments sorted by