
Most Python IoT backends run an MQTT broker as a separate service, usually Mosquitto, and then talk to it over a client library. That is one more process to deploy, configure and keep alive. Iotcore takes a different approach: it embeds the broker inside your Django or FastAPI application as a Python package, so pip install iotcore and a few lines of code give you a running MQTT broker on port 1883 with no external dependency.
The broker itself is written in Rust on the Tokio runtime and exposed to Python through native bindings. That is why it can handle thousands of concurrent connections without hitting Python’s global interpreter lock: the networking work happens in Rust threads, and Python only sees callbacks. If Rust is new to you, the introduction on this site explains why it is a good fit for this kind of job.
Features
- A configurable, Tokio-based MQTT broker with standard broker features.
- No Python GIL limitation: connections are handled in Rust.
- Zero extra setup to run the broker inside a Django or FastAPI project.
- A built-in MQTT client with callback support for async and non-blocking code.
Planned features
- Device support
- Sensor support
- Sensor data storage
- Django based admin pages
- Django rest framework based APIs for managing devices and sensors
- SSL certificates and policy management
Installation
pip install iotcore
Then create an mqtt.toml in the project root. Start from the sample configuration and adjust the port and limits as needed.
FastAPI setup
The simplest form starts the broker with the application and stops it on shutdown, using FastAPI’s lifespan hook:
Broker only
from fastapi import FastAPI
from iotcore.fastapi import iotcore_broker
app = FastAPI(lifespan=iotcore_broker)
@app.get("/")
def read_root():
return {"Hello": "World"}
To publish and subscribe from your own endpoints, create an IotCore instance and run its loop in the background:
Broker plus MQTT client
from fastapi import FastAPI
from contextlib import asynccontextmanager
from iotcore import IotCore
iot = IotCore()
@asynccontextmanager
async def lifespan(app: FastAPI):
iot.background_loop_forever()
yield
app = FastAPI(lifespan=lifespan)
@iot.accept(topic="temperature")
def temperature_data(request):
print(f"Temperature data : {request}")
def mqtt_callback(data):
print(f"iot >: {data}")
@app.get("/sub")
def sub():
iot.subscribe("iot", mqtt_callback)
return {"response": "subscribed"}
@app.get("/pub")
def pub():
iot.publish("temperature", "{'temp': 18}")
return {"response": "published"}
@app.get("/")
def home():
return {"Hello": "World"}
Django setup
Django has no lifespan hook, so start the background loop at import time in a module that loads once, such as apps.py or a dedicated mqtt.py:
from django.http import JsonResponse
from iotcore import IotCore
iot = IotCore()
iot.background_loop_forever()
def mqtt_callback(data):
print(f"Django >: {data}")
def subscribe(request):
iot.subscribe("iot", mqtt_callback)
return JsonResponse({"response": "subscribed"})
def publish(request):
iot.publish("iot", "demo")
return JsonResponse({"response": "published"})
With either framework running, the broker is listening on localhost:1883 and any MQTT client can connect.
Run the example project
Django
pip install iotcore
pip install django
python examples/django/manage.py runserver
FastAPI
pip install iotcore
pip install fastapi
pip install uvicorn
uvicorn examples.fastapi.main:app
Open an MQTT client such as MQTT Explorer or mosquitto_sub and connect to host 127.0.0.1, port 1883.
Links
- Documentation
- GitHub
- Issue tracker
- Zephyr RTOS guide for the device side of an MQTT setup
Support
If Iotcore saves you a Mosquitto deployment, star the project on GitHub; it helps others find it.
License
The project is licensed under the MIT license.

