I help teams fix systemic engineering issues: processes, architecture, and clarity.
→ See how I work with teams.
Summary
infinimesh is an Apache-2.0 IoT backend you run on your own servers. Version 3.4 is in release candidate testing now. It adds rules and alarms with CEL conditions, an OTA contract in the device shadow, a file service, fleet bulk updates, quotas, metrics, CoAP ingest, an audit log, and a stable v1 API. This post explains what changed, why it matters for EU device makers who want to keep their data at home, and how to try it on one machine in a few minutes.Bottom Line
Every connected product ends up building the same backend: a list of devices, rules about who may see them, and a record of what each device last said. I have built that backend more than once, and so have most teams I talk to. infinimesh is my attempt to stop doing it again.
Version 3.4 is the release where infinimesh grows from "registry and shadow" into a device layer you can actually run a product on. Rules and alarms, an OTA contract, files, fleet tools, quotas and metrics are now in core. The release candidates are out and being tested now. The final v3.4.0 tag is coming.
The practical takeaway: if you make devices in the EU and want the backend on your own servers under an open license, this is a good moment to try it and tell us what breaks.
What infinimesh is, in one paragraph
infinimesh is an open source IoT platform written in Go. It gives you a device registry, device auth with client certificates, a device shadow (reported and desired state), an MQTT bridge, and REST, gRPC and Connect APIs from one schema. Accounts, namespaces and devices form a permission graph, so a customer can see their devices at READ and their service partner can manage them, and neither sees anything past that. The project calls itself "the device layer for your IoT and AI stack", and that is the right scope. It is not a dashboard product. Your data goes to the tools you already run.
I co-founded infinimesh and I still maintain it. That is the bias you should read this post with.
How infinimesh 3.4 fits together
Devices in, state and events out. Everything in the blue box runs on your servers.
Desired state, rule actions and OTA targets flow back to the device over the same channel.
Why I care about where this runs
Most IoT platforms I see in projects are either a managed cloud service or an open core product where the parts you need in production sit in the paid edition. For a lot of European device makers both are a problem. The data leaves the building, or the license changes the math once the fleet grows.
infinimesh takes the other route. Apache-2.0, self-hosted, and the project says plainly that the open source core is complete and no feature is held back for a paid tier. Per customer access is in the core graph, not an upsell.
There is also the EU Data Act. If you sell connected products, your customers will ask for access to their device data, and sometimes for access by a third party they pick. 3.4 has the pieces for that: grants with an expiry date and a consent record, a device export endpoint that returns the registry entry and the current shadow, and an audit log of who read what. To be clear, and the project says the same: infinimesh gives you the access model. It does not make your product compliant by itself.
What is new in 3.4
What's new in infinimesh 3.4
From the core changelog, v3.4.0 release candidates
Rules and alarms
CEL conditions such as reported.temp > 70. Alarms are raised, acked or cleared, with a cooldown. Actions: log, signed webhook, MQTT, desired state.
OTA contract
Target version in desired state, status reported back. Only a registered OTA addon, such as hawkBit or Mender, can enable OTA for a namespace.
Files (http-fs)
Namespace files for the console media page. Local volume by default, or any S3 endpoint. Size and type limits.
Fleet bulk patch
One desired state for every device in a namespace or with a tag. Bulk create, factory claim tokens, certificate rotation and revocation.
Quotas
Per namespace limits on devices and message rates, on the MQTT bridge and on HTTP ingest. Zero means no limit.
Metrics and traces
/metrics on every service for Prometheus. OTLP trace export with one environment variable.
CoAP ingest
Reported state over UDP CoAP on 5683. Plaintext, so keep it on a private network.
Audit log
Append only. Shadow reads, device creation, device tokens and OTA assigns, queryable by device or account.
v1 API
REST under /v1, gRPC and Connect from one proto schema. Breaking changes go into a new version. OpenAPI spec and Swagger view online.
Kubernetes and Compose
Helm chart for production, Docker Compose on one machine for local work.
inf CLI
A single Go binary. brew install inf on macOS and Linux, archives for Windows.
Air-gapped install
An offline bundle per release for Docker and Kubernetes. Open proposal, not built yet.
OTA addons
hawkBit and Mender addons that plug into the OTA contract.
MCP server and LLM addon
Device state for AI agents and OpenAI compatible APIs, scoped by the same permission graph.
Rules and alarms
This was the biggest gap. Until now the honest answer to "where do I put my alert logic" was "in another system". In 3.4 rules live in core.
A rule belongs to a namespace. The condition is a CEL expression that can read reported, desired, connected, the device, its title, its tags and the namespace. A reading stored at reported.data.temp is just reported.temp in the rule. So reported.temp > 70 does what you think it does.
When the condition is true, the rules service raises an alarm for that rule and that device. Someone can ack it, it clears when its clear condition is true, and a cooldown sets the shortest time before the same alarm can be raised again. Actions are a log line, a webhook signed with HMAC-SHA256, an MQTT publish, or a patch to the device's desired state. That last one is the useful one: a rule can tell the device to do something, not only tell a human.
Two details I like. A new rule is checked against the current state of every device right away, not on the next reading. And you manage rules and alarms over REST (/v1/rules, /v1/alarms) or the Connect API, the same way the console does.
OTA as a contract, not a feature
I did not want infinimesh to become yet another firmware server. hawkBit and Mender already do that job well. What was missing was a clean place in the device layer where "this device should run version X" and "this device is now downloading, installing, done or failed" live.
So 3.4 adds an OTA document to the shadow. The target version, URL, SHA-256 and size go into desired state. The device reports its status back. POST /v1/devices/ota:assign sets a target for a list of devices, a tag, or a whole namespace, returns one result per device, and writes an audit row for each success.
The important rule: OTA stays off for a namespace until an OTA addon is registered for it. Nothing can write the desired OTA target while it is off. The addons for hawkBit and Mender come after 3.4. Until then the contract is there for you to build against.
Fleet, quotas and the boring production parts
Bulk create, factory claim tokens, certificate rotation that keeps the previous certificate valid during rollover, and revocation. A device can claim itself into a namespace with a factory token and its certificate, which matters a lot once you produce hardware in batches. I wrote about why the factory side needs its own evidence trail in IoT device manufacturing needs verifiable assembly records. infinimesh is the place where that device identity lands after it leaves the line.
Then the part nobody demos: per namespace quotas on device count and message rates, Prometheus metrics on every service, OTLP traces, and MQTT sessions that can live in Redis so a reconnect can land on another bridge replica. This is what lets you run it for customers instead of for yourself.
CoAP, files, and a stable API
CoAP ingest is for constrained devices that cannot afford MQTT over TLS. It is plaintext UDP with no DTLS, so treat it like a field bus: private network only, or a terminator in front. Same honesty as with BACnet. Protocol bridges look small and turn into infrastructure, which is the whole point of my posts on the real cost of bridging BACnet to MQTT and on bacnet-mqtt-gateway. A building gateway that publishes to infinimesh over MQTT is a very normal setup.
The http-fs service stores files per namespace, on a local volume or any S3 endpoint such as MinIO or Hetzner Object Storage. And the v1 API is now stable: new fields can be added, breaking changes go into a new version. You can browse it in the API reference, which is a Swagger view of the OpenAPI spec.
Try it on your laptop
You need Docker with Docker Compose. This runs the whole stack on one machine. To test the 3.4 release candidate, pin it in .env:
git clone https://github.com/infinimesh/core.git
cd core
cp .env.example .env
# test the 3.4 release candidate
sed -i.bak 's/^INFINIMESH_VERSION=.*/INFINIMESH_VERSION=v3.4.0-rc.6/' .env
docker compose up -d
Open https://console.127.0.0.1.nip.io and log in as infinimesh / infinimesh. Change that password right away. The local setup uses a self-signed certificate, so accept it once each for console, api and media. If login fails with no message, you have not accepted the api one yet.
Get the CLI:
brew tap infinimesh/inf-cli https://github.com/infinimesh/inf-cli
brew install inf
Then create a rule that raises an alarm when a device runs hot. Use the namespace id from inf namespaces list:
API=https://api.127.0.0.1.nip.io
TOKEN=$(curl -sk -X POST "$API/v1/token" \
-d '{"auth":{"type":"standard","data":["infinimesh","infinimesh"]}}' \
| python3 -c 'import sys, json; print(json.load(sys.stdin)["token"])')
curl -sk -X POST "$API/v1/rules" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"namespace": "<namespace-uuid>",
"name": "Too hot",
"when": "reported.temp > 70",
"clear": "reported.temp < 65",
"cooldown": "10m",
"actions": [{"log": {"message": "temperature above 70"}}]
}'
Send a reading above 70 from a device, with inf devices state, an ESP32 or Pico W example, or the curl script in the docs repo, and the alarm shows up on the "Rules and Alarms" page.
For production, use the Helm chart in infinimesh/k8s. An air-gapped install for factories, labs and regulated sites is planned as an open proposal. If you need it, comment there.
When not to use it
- You want a fully managed cloud service and do not want to run servers.
- You want dashboards in the box. Use Grafana on top of an addon, or a different product.
- You have a few devices and one user. A plain MQTT broker is simpler.
- You need OTA end to end today. The contract is in 3.4, the hawkBit and Mender addons are not.
What comes after 3.4
First the OTA addons, so hawkBit and Mender plug into the contract above. Then AI, which is where the tagline comes from. An MCP server will let an agent read device state and set desired state, and an LLM addon will send device state to any OpenAI compatible API, such as vLLM, Ollama or Mistral. Both are coming soon and neither is built yet.
The part I care about is that both will be scoped by the same permission graph as people. An agent sees only the devices its token can see. You can run the model locally, so device data stays on your servers. Until those ship, the webhook or MQTT bridge addon is the way to feed your own agent.
Videos
A few older videos about the platform, made with my startup Infinite Devices, which I founded with my friend Bruno in 2021 and sold in 2024. They are in German and show earlier versions, but the idea has not changed: IoT data under your control.
Infinite Devices: Infinimesh, skalierbare Open-Source-AIoT-Plattform (2022, German)
Infinite Devices at ITT21: IoT, the eyes and ears of AI (2021, German)
More from the archive:
- Connect, Control, Collaborate, Infinite Devices on infinimesh and GDPR (2021, German)
- midimesh/infinimesh as part of an AIoT music lecture at MusicTech Meeting Berlin (2023)
- Infinite Devices presents Midimesh at Superbooth 2023 in Berlin (German)
- Back to the Future of AI, Ep. 7 with Bruno Kramm, CEO of Infinite Devices (2022, German)
Star it, run it, break it
If you build connected hardware and want to own the backend, give it ten minutes. If the quickstart runs on your machine, it is worth a closer look. If it does not, that is a bug and I want to hear about it.
- Code: github.com/infinimesh/core. A star helps other people find it.
- All repos, addons and device examples: github.com/infinimesh
- Project site: infinimesh.org
- Release candidates and notes: core releases
- Bugs and questions: GitHub issues
infinimesh is also listed on the Scalytics open source page.
If you need help with distributed systems, backend engineering, or data platforms, check my Services.