Polars 2.0 makes the streaming engine the default
The Rust-based dataframe library adds out-of-core spilling, first-class SQL support and a native Map type, and silently drops row-order guarantees unless you opt back in.
Polars shipped version 2.0 on 6 October. Calling collect() on a LazyFrame now runs through the streaming engine by default, and out-of-core execution is on by default too: once memory use hits roughly 80% of RAM, Polars spills to disk, with a 64GB budget out of the box. That means queries over datasets bigger than RAM no longer need a separate engine.
It’s a breaking change as well as a feature: the streaming engine doesn’t guarantee row order for joins, group-bys and unpivots unless you set maintain_order=True.
df.lazy().group_by("key").agg(pl.col("value").sum()).collect(maintain_order=True)
The release also makes SQL a first-class interface, with join reordering, common-subplan elimination and bloom filters in the optimiser; adds a native Map dtype for Arrow’s MapType, replacing the old List(Struct) workaround; and tightens implicit type coercion so schema mismatches surface earlier instead of silently coercing.
Why it matters: anyone running Polars in a pipeline should check for unordered joins and group-bys before upgrading — code that happened to rely on row order can produce different output with no error. The out-of-core default also means a job that used to run out of memory may now just run slower, which is worth knowing before it surprises you in production.
The caveat: the TPC-H and TPC-DS benchmark claims against DataFusion and DuckDB are Polars’s own.