Polars 2.0 RC1 Makes Streaming the Default Engine
Ritchie Vink released Polars 2.0 RC1 today, and the headline is one line: collect() now defaults to the streaming engine. This is the kind of breaking change that justifies a major version — and the kind that makes every Polars user's life better without them doing a thing.
What Shipped in Polars 2.0 RC1
Three structural changes define this release:
Streaming engine as default. Every LazyFrame.collect() call now resolves to the streaming engine instead of the in-memory engine. This means dramatically lower memory usage and better performance on most queries out of the box. The tradeoff: row order is no longer guaranteed for joins, group_by, and unpivot operations. If you need observable row order, opt in with maintain_order="left" on joins or set pl.Config.set_engine_affinity("in-memory") process-wide to revert to the old behavior.
Strictness by default. Polars has always prided itself on failing fast. 2.0 cranks that up. Silent type coercion is gone — is_in across mismatched types now raises InvalidOperationError instead of silently producing wrong results. Horizontal concat checks row counts instead of padding with nulls. Casting strings to dates requires explicit .str.to_date() rather than implicit .cast(pl.Date). Every one of these changes is a footgun removed from the data pipeline.
API cleanup with guardrails. Removed methods and renamed parameters get typed exceptions — AttributeRemovedError and ArgumentRemovedError — that point directly to the replacement API. The migration guide is already live at pola.rs.
Why It Matters for Data Pipelines
Polars positioning 2.0 as a "boring" release is itself interesting. The project doesn't gate features behind major versions — streaming, the new IO plugin system, out-of-core support, and the S3 reader all ship incrementally. 2.0 is about defaults, not features. That's the sign of a maturing project: it has enough confidence in its architecture to change what "normal" means.
For anyone running data pipelines or building agentic systems that touch dataframes: the streaming default alone is worth the upgrade. Your memory ceiling drops. Your large-join performance improves. And the strictness changes mean bugs that used to surface 20 minutes into a pipeline now raise at compile time. If you've ever debugged a silent float64 overflow on a user ID column, you know why that matters.
Try it: pip install polars==2.0rc1. The final 2.0 release lands in the coming weeks.