One semantic model. Multiple ways to think.
Write data logic once.
Run it anywhere.
Inspect everything.
IncQL unifies query blocks, DataFrame-style chains, LazyFrames, and pipelines into one typed relational model. Prism lets you see exactly what the compiler sees before execution.
The problem with data logic today
Teams lose time to expression, semantics drift, and opaque pipelines that lock them to engines.
Too many ways to express logic
SQL, DataFrames, pipelines, and notebooks each carry their own shape.
Different semantics and behaviors
Small rewrites can change meaning before anyone sees the plan.
Hard to inspect and debug
You see results, but not the logic, lineage, or rechecking behavior.
Tied to specific engines
Porting usually means rewriting logic and revalidating behavior.
IncQL is the unifying layer
Different surfaces. One compiler. Multiple execution targets.
Query blocks
Python, Rust, JS
Polars, Ibis, DataFusion
Airflow, dbt, custom
IncQL
Typed relational model
- Schema flow
- Lineage
- Optimizer choices
- Type-checked
How IncQL works
Author in the surface that fits the task. IncQL keeps the semantics attached as the work moves from intent to execution.
Author
Write in the interface that matches your workflow and context.
- Query blocks
- DataFrames
- LazyFrames
- Pipelines
Compile
Lower authoring intent into a typed relational model and Substrait plan.
model Order:
id: int
status: str
region: str
Substrait
Prism
IncQL's semantic core makes the compiler's decisions visible.
- Schema flow
- Lineage
- Projections
- Filters
- Optimizer choices
Optimize
Apply rule- and cost-based optimizations for the best execution plan.
- Aggregate
- Filter
- Project
- Scan
Smart optimizer
Execute
Run on the engine that fits: local, in-process, or distributed.
- DataFusion
- DuckDB
- Spark
- Substrait
Inspect before execution
Prism makes the compiler visible
IncQL plans are not opaque strings handed to a backend engine. Prism exposes the typed model and evidence before execution.
query {
FROM orders
WHERE .status == "paid"
GROUP BY .region
SELECT
.region as region,
sum(.amount) as total
}
Source(orders)
Filter(status == paid)
Aggregate(group: region)
Project(region, total)
- DataFusion
- DuckDB
- Spark
- Other Substrait consumers
Semantic convergence
One language. Many surfaces.
Different ways to write. Same plan. Same result.
query {
FROM orders
WHERE .status == "paid"
ORDER BY desc(.amount)
LIMIT 20
}
SELECT *
FROM orders
WHERE status = 'paid'
ORDER BY amount DESC
LIMIT 20;
preview = (
orders
.where(orders["status"] == "paid")
.sort_values("amount", ascending=false)
.head(20)
)
preview = orders
.filter(eq(col("status"), "paid"))
.order_by([desc(col("amount"))])
.limit(20)
preview = orders
|> where .status == "paid"
|> order_by .amount desc
|> limit 20
Same Prism plan
- SourceRead the same typed relation.
- FilterApply the same predicate semantics.
- OrderKeep descending amount order attached.
- LimitReturn the same preview window.
Confidence by construction
Built for trust
- Static typing and schema flow for confidence
- Prism for deep visibility before execution
- Deterministic, backend-neutral semantics
- Reproducible, testable, observable evidence
A surface developers can own
Engineered for developers
- Familiar when you know SQL or DataFrames
- Powerful when governance matters
- Extensible, open, and community-driven
- Designed for humans and AI agents
Start with inspectable data logic
Ready to experience IncQL?
Start with a quickstart, explore examples, or jump straight into the reference.