Open-source streaming SQL

Process streaming data with SQL.

Read events from Kafka and other sources, keep SQL results current as they arrive, and send them to a sink or query them directly.

  1. 01 / Source
  2. 02 / Query
  3. 03 / Result
Conceptual data flow

How it works

A pipeline is three
SQL statements.

  1. CREATE SOURCE names the topic, its columns and the watermark: how long to wait for events that arrive late.
  2. CREATE STREAM is the continuous query. This one totals each symbol's volume per minute and emits a row when the watermark passes the end of the minute.
  3. CREATE SINK writes every emitted row to another Kafka topic.
pipeline.sql
CREATE SOURCE trades (
    symbol VARCHAR NOT NULL,
    price  DOUBLE NOT NULL,
    volume BIGINT NOT NULL,
    ts     TIMESTAMP NOT NULL,
    WATERMARK FOR ts AS ts - INTERVAL '5' SECOND
) FROM KAFKA (
    'bootstrap.servers' = 'kafka:9092',
    'topic' = 'trades',
    'group.id' = 'minute-volume',
    'startup.mode' = 'earliest'
) FORMAT JSON;

CREATE STREAM minute_volume AS
    SELECT symbol,
           tumble(ts, INTERVAL '1' MINUTE) AS minute,
           SUM(volume) AS volume,
           MAX(price) AS high
    FROM trades
    GROUP BY symbol, tumble(ts, INTERVAL '1' MINUTE)
    EMIT ON WINDOW CLOSE;

CREATE SINK minute_volume_out FROM minute_volume
    INTO KAFKA ('bootstrap.servers' = 'kafka:9092', 'topic' = 'minute-volume')
    FORMAT JSON;
minute-volume topic, after five trades
{"symbol":"AAPL","minute":"2026-10-18T09:30:00","volume":150,"high":189.7}
{"symbol":"AAPL","minute":"2026-10-18T09:31:00","volume":70,"high":189.6}
{"symbol":"MSFT","minute":"2026-10-18T09:30:00","volume":30,"high":411.2}

The last trade was MSFT at 09:32:30, so the watermark stands at 09:32:25 and the 09:32 window stays open until a later event arrives. Run this example with the steps in the README.

Deployment

One engine, three ways to run it.

  • Embedded

    Add the laminar-db crate to a Rust program. Pipelines run inside your process and checkpoint to a local directory.

    cargo add laminar-db

  • Single server

    Run the laminardb binary or Docker image with a TOML file. It serves SQL over HTTP, WebSocket subscriptions and Prometheus metrics, with an optional PostgreSQL wire endpoint.

    laminardb/laminardb-server:0.33.0

  • Cluster

    Several servers share checkpoints in S3, Google Cloud Storage or Azure storage and find each other by gossip or a static list. Sources must be Kafka, and materialized views and AI functions are not available.

    Cluster SQL limits

Quick start

Run a continuous
query locally.

You need Docker. The built-in generator source emits numbered rows at a fixed rate, so nothing else has to be running.

The view keeps its totals current as rows arrive. Query it twice a few seconds apart and the numbers move. Counts come back as strings because 64-bit integers do not fit in JavaScript numbers.

1. Save as laminardb.toml
sql = '''
CREATE SOURCE ticks FROM GENERATOR ('rows.per.second' = '10');

CREATE MATERIALIZED VIEW tick_totals AS
    SELECT COUNT(*) AS rows_seen, MAX(seq) AS last_seq
    FROM ticks;
'''

[server]
mode = "single"
bind = "0.0.0.0:8080"
console_token = "${LAMINAR_CONSOLE_TOKEN}"

[checkpoint]
url = "file:///var/lib/laminardb/checkpoints"
interval = "10s"
2. Start the server
export LAMINAR_CONSOLE_TOKEN="$(openssl rand -hex 32)"
docker run --rm -d --name laminardb -p 127.0.0.1:8080:8080 \
  -e LAMINAR_CONSOLE_TOKEN \
  -v "$PWD/laminardb.toml:/etc/laminardb/laminardb.toml:ro" \
  laminardb/laminardb-server:0.33.0
3. Query the view
curl -s http://localhost:8080/api/v1/sql \
  -H "Authorization: Bearer $LAMINAR_CONSOLE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"sql": "SELECT * FROM tick_totals"}'
Output (your numbers will differ)
{"result_type":"query","data":[{"rows_seen":"46","last_seq":"45"}]}

Stop it with docker stop laminardb. The commands are for a Bash-compatible shell.

LaminarDB Console

Work with your running system.

The Console is a browser app for a LaminarDB server you run. Browse sources, streams and sinks, run SQL, follow checkpoints and Prometheus metrics, and see how objects connect. It calls the server's HTTP API with your console token.

Open the Console

Connects from your browser to your own server; your browser may ask permission to reach a local address. Setup notes

LaminarDB is pre-1.0. Test your workload, delivery requirements and recovery path before relying on it in production. Read the production guidance.