The data runtime for teams that ship.
No setup. No services. No stack.
One binary replaces ingestion, transformation, and orchestration.

-- @kind: merge
-- @unique_key: order_id
-- @incremental: updated_at
-- @constraint: order_id PRIMARY KEY
-- @audit: row_count > 0
SELECT
order_id,
customer_id,
order_date,
total_amount,
status
FROM raw.ordersYou don't need a data stack anymore
Event → Data → Query
From event to queryable data in one system. No message broker. No ingestion layer. No orchestrator.
Runs Locally
Runs on one machine. No cluster. No cloud. No setup. Install, init, run.
Every Change Tracked
Every run is reproducible. Snapshots track every change. Rollback with time-travel.
Preview Before You Ship
Preview all changes before committing. See diffs, schema evolution, downstream impact — then decide.
No Connectors to Install
Call any API directly. HTTP, OAuth, pagination — all built in. No connectors to install. No Python.
Quality Built In
26 constraints block bad data. 17 audits catch regressions. Column lineage tracks every field. Schema evolves without migrations.
SQL + Scripts + Config
SQL for transforms. Starlark for connectors. YAML for config. One pipeline.
Built-in Event Collection
POST events to an embedded endpoint. Durable buffering. Exactly-once flush. No Kafka.
One command replaces your pipeline stack
You don't configure pipelines. You run them.
1. Install
curl -fsSL https://ondatra.sh/install.sh | sh
2. Write SQL
Place SQL files in models/. Add @kind, @incremental, @constraint as comments.
3. Run
ondatrasql run — DAG built, changes detected, data materialized.
SQL, scripting, and validation — in one pipeline
Transform data with plain SQL. The framework handles materialization and change detection automatically.
-- @kind: scd2
-- @unique_key: customer_id
-- @constraint: customer_id NOT NULL
-- @constraint: email EMAIL
SELECT
customer_id,
name,
email,
tier,
region
FROM raw.customersIngest from REST APIs with Starlark scripts. Built-in HTTP, OAuth, and pagination support.
# @kind: merge
# @unique_key: id
resp = http.get(
"https://api.example.com/users",
headers={"Authorization": env.get("API_TOKEN")},
)
for user in resp.json:
save.row(user)Preview every change before committing. See skips, diffs, schema evolution, and downstream propagation.
╠═══ Execution ════════════════════════════╣
[OK] raw.customers (45ms)
[OK] staging.customers (128ms)
[OK] staging.orders (95ms)
[OK] mart.revenue (54ms)
╠═══ Summary ══════════════════════════════╣
Unchanged: 2 models
Changed: 2 models
╠═══ Changes ══════════════════════════════╣
staging.orders
Rows: 100 → 142 (+42, +42.0%)
+ Added: 42 rows
mart.revenue
SCHEMA EVOLUTION:
+ Added: region (VARCHAR)
Rows: 5 → 6 (+1, +20.0%)Get started in minutes
Download the binary, init a project, write your first model, and run it.
Ondatra Labs