Realtime channels ⚡- RPC, PUB/SUB at scale 
Tags: python, pubsub, webdev, microservices
Published: 2021-03-23 14:20:27

As modern software is exploding (especially in the cloud and at the edge) the need to deliver realtime **data, updates**, and **events** at scale across deployed instances is ever increasing.
A challenge we had to solve for our own fullstack authorization as a service solution ([authorizon.com](https://www.authohorizon.com))
That's why we've created [⚡ FastAPI-websocket-RPC](https://github.com/authorizon/fastapi_websocket_rpc) and [🗞️ FastAPI-websocket-PubSub](https://github.com/authorizon/fastapi_websocket_pubsub).
# Why Websocket-RPC ?
Often you'd like to trigger events and/or access code on the client side (and not just on the server). Explicitly exposed RPC methods are the easiest way to go about it.
Each side (both client and server) can expose Python methods like this:
```python
class RpcCalculator(RpcMethodsBase):
    async def add(self, a, b):
        return a + b
```
And the other-side can call them (and wait for a response with a return value) like this:
```python
response = await channel.other.add(a=1,b=2)
print(response.result) # 3
```
## Pub/Sub
Similarly Pub/Sub is the easiest way to have different services share updates.
Once a server is up:
```python
app = FastAPI() 
endpoint = PubSubEndpoint()
endpoint.register_route(app, "/pubsub")
```
clients can then subscribe
```python
async with PubSubClient(server_uri="ws://localhost/pubsub") as client:
# Callback to be called upon event being published on server
async def on_event(data):
    print("We got an event! with data- ", data)
# Subscribe for the event 
client.subscribe("my_event_topic", on_event)
```
and publish
```python
async with PubSubClient(server_uri="ws://localhost/pubsub") as client:
    endpoint.publish(["my_event_topic"], data=["my", "data", 1])
```
With ease 😇
# Why Realtime / Websocket?
Polling systems are the worst - constantly creating overhead, and are always delayed and suffering from consistency issues. Websockets are ideal for traversing the cloud and the internet. Thanks to running on top of an initially **outgoing** HTTP connection, all the common issues one would face with firewalls and routing for most bi-directional channels are inherently solved. When push comes to shove - software should always push rather than pull 😜.
# Why on top of FastAPI
With Python, asyncio, Starlette, and Pydantic at its core, FastAPI provides great performance (still not as good as GO, but comparable/superior to Node.js) and enjoys the dev-speed and maintainability of typed Python. Its dependency injection mechanism allows our RPC and PubSub to easily enjoy all the benefits of the underlying HTTP (Such as authorization, cookies, routing) with easy configuration.
# Performance
While we haven't created official benchmarks yet, we have successfully run these packages in production with 100s of events per second, per server instance, with no issue. In addition instances can scale horizontally with ease (thanks to the broadcasting mechanism).
# Pub/Sub - Why not RabbitMQ, etc. ?
First,  RabbitMQ is great - but it's not a cure-all;  
[FastAPI WS Pub/Sub](https://github.com/authorizon/fastapi_websocket_pubsub) allows to decouple the backbone Pub/Sub (such as RabbitMQ, Kafka, or Redis) from the API layer - which is more lightweight. Bringing tons of benefits:
- Allowing to scale-out the lightweight layer without having to scale-out the backbone (which is often much more resource intensive) 
- Being able to work with the native API (e.g. REST, GraphQL) in tandem (being part of the same framework or even process)
- Choosing whichever backbone Pub/Sub channel you'd like, and being able to easily switch (no lock-in).
- Code level control - this solution embeds into your Python code, you don't have to look at it as a blackbox (unless you want to).

# Bottomline
Realtime data propagation is becoming a common task, and we hope these open-source packages would make it easier for everyone to accomplish.
[Take them for a spin](https://github.com/authorizon/fastapi_websocket_pubsub) and [tell us what you think](https://github.com/authorizon/fastapi_websocket_rpc/discussions)