Native OT + IT Protocol Ingestion
Ingest Modbus TCP/RTU, OPC-UA, MQTT v3.1.1/v5, Kafka, Redis, and OTLP without separate protocol-translation containers.
Explore connectors
rekuiper is a single-binary MQTT rule engine and streaming SQL processor written in Rust. It runs on edge gateways between devices and cloud networks—filtering, aggregating, and routing live MQTT, Kafka, Modbus, and OPC-UA telemetry at 1,000,000–2,200,000+ events per second per core.
You write a rule in SQL. rekuiper executes the rule on every message when the message arrives. You add, change, and remove rules through a REST API while the engine runs.
What changes when you deploy rekuiper on the edge:
This demo requires Docker. A built-in simulator generates sensor readings.
1. Start the engine.
docker run -d --name rekuiper -p 9081:9081 indusstack/rekuiper:1.0.0-rc4Built-in Web Observability UI
Open http://localhost:9081/ui in your browser to inspect live streams, rules, and rule metrics without installing companion containers.
2. Register simulated sensor readings (ten events per second).
curl -X PUT http://localhost:9081/metadata/sources/simulator/confKeys/demo \
-H "Content-Type: application/json" \
-d '{
"data": [
{"deviceId": "pump-1", "temperature": 21.5},
{"deviceId": "pump-1", "temperature": 23.0},
{"deviceId": "pump-1", "temperature": 24.5}
],
"interval": 100,
"loop": true
}'3. Create a stream to ingest the readings.
curl -X POST http://localhost:9081/streams \
-H "Content-Type: application/json" \
-d '{"sql": "CREATE STREAM demo () WITH (TYPE=\"simulator\", CONF_KEY=\"demo\")"}'4. Add a rule to aggregate five seconds of readings into one row.
curl -X POST http://localhost:9081/rules \
-H "Content-Type: application/json" \
-d '{
"id": "five_second_summary",
"sql": "SELECT count(*) AS readings, avg(temperature) AS avg_temp FROM demo GROUP BY TUMBLINGWINDOW(ss, 5)",
"actions": [{ "log": {} }]
}'5. Verify the output.
docker logs -f rekuiper[RULE five_second_summary] Matched record: {"readings": Number(49), "avg_temp": Number(23.03)}Fifty readings enter the pipeline. One row exits. To route this row to MQTT, Kafka, or a database, replace log with another sink.
Continue with the Getting Started Guide.
Each pattern requires one or two SQL rules.
Devices publish every second. Cloud analytics require one row per minute. Aggregate on the gateway and send the summary.
SELECT deviceId, avg(temperature) AS avg_temp, max(temperature) AS max_temp
FROM sensors
GROUP BY deviceId, TUMBLINGWINDOW(ss, 60)Read more: Windows
A sensor value crosses a safety threshold. Filter on the gateway and publish an MQTT command or call a webhook immediately. The alert does not wait for cloud round trips.
SELECT deviceId, temperature, meta(topic) AS source_topic
FROM sensors
WHERE temperature > 80Read more: Rules · REST sink · MQTT sink
The cellular or WAN uplink drops for minutes or hours. Enable the sink cache. Results buffer on disk, and rekuiper resends them in order when the link reconnects.
{
"mqtt": {
"server": "tcp://cloud.example.com:1883",
"topic": "site1/summary",
"enableCache": true
}
}Read more: Sink cache
One data feed routes to storage, to a dashboard, and to an alert topic. Multiple rules subscribe to one stream. Each rule defines its own SQL and destinations.
| Rule | SQL | Destination |
|---|---|---|
| Archive | SELECT * FROM sensors | Parquet files on local disk |
| Dashboard | One-minute averages per device | InfluxDB |
| Alert | WHERE temperature > 80 | MQTT command topic |
Read more: Sinks
Messages carry a device ID. Upstream applications require site and asset names. Join the stream with a lookup table in Redis or a SQL database.
SELECT s.deviceId, s.temperature, a.site, a.asset_name
FROM sensors AS s
INNER JOIN assets AS a ON s.deviceId = a.idRead more: Lookup tables
Use rekuiper when... | Look elsewhere when... |
|---|---|
| Your data arrives from OT or IT protocols: Native MQTT, Modbus TCP/RTU, OPC-UA, HTTP, WebSocket, Kafka, AMQP/RabbitMQ, Redis, OTLP, or ZeroMQ. | You need legacy building-automation protocols not yet built in (e.g., native BACnet or PROFINET without a protocol converter). |
| You want streaming logic in SQL (tumbling/hopping/sliding/session windows, joins, analytic functions) managed via REST API, CLI, or Declarative GitOps YAML. | You want a drag-and-drop visual wiring tool for non-SQL users (use Node-RED for low-volume visual scripting). |
| Your edge hardware is constrained (1–2 CPU cores, 64 MB–512 MB RAM) and cannot tolerate Go/JVM garbage-collection pauses or 500 MB+ container images. | You need a multi-node distributed cloud shuffle cluster (use Apache Flink or Spark Streaming for datacenter-scale petabyte joins). |
You need offline resilience & local sinks: Disk-backed sink cache (sink_cache.rs), Dead-Letter Queues (dlq.rs), and direct writes to Parquet, InfluxDB v1/v2, TDengine, IoTDB, or SQL databases. | You only need stateless log forwarding without windowed aggregations, stateful joins, or local rule evaluation (use Vector or Telegraf). |
You are building AI-assisted IoT operations: Native Model Context Protocol (rekuiper-mcp) lets AI agents inspect schemas, dry-run SQL rules, and diagnose live pipelines. | You only need basic protocol passthrough without filtering, enrichment, or stateful edge computations. |
All tests run on dedicated Linux hardware constrained to one physical CPU core and 1 GiB of RAM.
| Measure | Result | Tested on |
|---|---|---|
| In-process stream throughput (Zero-parse) | 2,207,367 events/s (500k in 226 ms, 0 ms drain) | 1.0.0-rc4 |
| End-to-end JSON stream throughput | 1,085,885 events/s (500k in 460 ms, 0 ms drain) | 1.0.0-rc4 |
| MQTT network throughput (Single rule) | 150,000 to 200,000 messages/s (0.00% loss) | 0.500 |
| Concurrent rules on one stream | 1,000 rules (500,000 evaluations/s) | 0.505 |
| Heap memory under load | 4.4 to 10.2 MiB (Flat plateau, zero GC pauses) | 1.0.0-rc4 |
| Static binary footprint | ~30 MB (Self-contained, zero external deps) | 1.0.0-rc4 |
| Capability | rekuiper (1.0.0-rc4) | eKuiper 2.4.1 | Performance Delta |
|---|---|---|---|
| In-process stream throughput | 1,000,000+ events/s | N/A (Embedded runtime only) | Native Rust speed |
| Network MQTT throughput | 150,000 to 200,000 msg/s | ~20,000 msg/s | 8x to 10x throughput |
| Parallel rule scaling | 1,000 concurrent rules | ~100 rules | 10x rule capacity |
| Memory stability | 4.4 to 10.2 MiB (Flat) | 15 to 886 MiB (GC spikes) | Zero GC jitter, no OOM |
| Garbage collection | None (Deterministic ownership) | Present (Stop-the-world sweeps) | Zero tail-latency spikes |
Method and full results: Benchmark Overview · Throughput · Parallel rules
| Sources (data in) | Sinks (data out) | |
|---|---|---|
| Messaging | MQTT, Kafka, RabbitMQ, Redis, ZeroMQ, WebSocket | MQTT, Kafka, RabbitMQ, Redis, ZeroMQ, WebSocket |
| HTTP | HTTP pull, HTTP push | REST |
| Databases | PostgreSQL, SQLite | PostgreSQL, SQLite, InfluxDB v1 and v2, TDengine, IoTDB |
| Files and media | CSV, JSON Lines, Parquet, video (FFmpeg) | CSV, JSON Lines, Parquet, image |
| Industrial | Modbus TCP/RTU, OPC-UA, EdgeX Foundry, Neuron | Modbus TCP/RTU, OPC-UA, EdgeX Foundry, Neuron |
| Telemetry | OpenTelemetry (OTLP/HTTP metrics, logs, traces) | OpenTelemetry (OTLP/HTTP) |
| Test | Simulator, Memory | Log, Memory, Nop |
| I want to | Go to |
|---|---|
| Build my first real pipeline with MQTT | Getting Started Guide |
| Install on a gateway, in Docker, or in Kubernetes | Installation and Deployment |
| Learn the SQL | SQL Reference |
| Understand how the engine works | Architecture |
| Move from eKuiper | Migration guide |
| Automate with the REST API or CLI | REST API · CLI |
| Inspect pipelines with zero companion containers | Embedded UI & rekuiper top |
| Manage distributed gateways with staged canary rollouts | Fleet Management & Control Plane |
| Design multi-port streaming DAGs with live wire-tap | Visual Stream DAG Studio |
| Use an AI coding assistant with rekuiper | Model Context Protocol |