Polars 2.0 Makes Streaming the Default and Stops Promising Row Order
Software / explainer
Polars 2.0 Makes Streaming the Default and Stops Promising Row Order
The release, announced Oct. 6 by creator Ritchie Vink, adds no headline feature, but a join or group-by that used to return rows in input order may now return them in any order.
Polars 2.0 changed the default engine for every lazy query to the streaming engine on Tuesday, and that engine does not guarantee row order for joins, group-bys or unpivot. Code that never sorted because the old engine happened to keep input order will still run. It may return the same rows in a different sequence.
Creator Ritchie Vink announced the release in a post on the Polars site dated Oct. 6, 2026. The project's upgrade guide lists the breaking changes, and its own wording on this one is blunt: the streaming engine "does not guarantee row order for operations that don't require it." The guide adds that joins are "easy to miss since nothing about the query looks order-sensitive."
That second sentence is the one to read twice. A query that ends in a join and a write_csv gives no sign that its output order was ever a property worth testing.
The row-order change in practice
Calling collect on a LazyFrame, Polars' deferred query object, now resolves its engine="auto" setting to streaming. Before 2.0, lazy queries defaulted to the in-memory engine, which kept rows where the input had put them. The fix is to add maintain_order=True to the operation, or to sort explicitly before the result matters.
The design was argued over before it shipped. On a Hacker News thread about the pre-release, a commenter objected that non-deterministic defaults are a hazard in scientific work: "the correct answer is not known in advance, so bugs can slide by and silently give incorrect results." Other commenters on the thread defended the choice as matching SQL semantics, where an unordered result is the contract, and as the price of the speed.
What else breaks on upgrade
Vink's post calls 2.0 a cleanup release, and the upgrade guide reads like one. The changes below are the ones most likely to hit an existing pipeline without raising an error on the first run.
| Change in 2.0 | Old behaviour | What to do |
|---|---|---|
Signed int with UInt64 | Result cast to Float64, losing precision | Expect Int128 |
scan_csv() with a schema | Matched columns by position | Matches by header name |
| Multi-file CSV scan | Inferred schema from all files | Reads only the first 10 files |
| Headerless CSV columns | Named from column_1 | Named from column_0 |
explode() on empty list | Produced one null row | Produces zero rows; empty_as_null=True restores the old result |
Reading from io.BytesIO | Rewound to the start | Starts at current position; call buf.seek(0) |
The BytesIO item is the friction most notebook users will meet first. The pattern of writing a Parquet file into a buffer and passing the buffer straight to pl.read_parquet stops working until buf.seek(0) is added.
Some changes are loud. Casting a String column directly to Date, Datetime or Time now raises, so str.to_date() and its siblings are required. melt is gone in favour of unpivot, with_row_count in favour of with_row_index, and LazyFrame.profile() is removed outright. SQL queries run through pl.sql() are no longer parsed on the spot, so a syntax or schema error surfaces at collect() rather than when the query is written.
The silent ones matter more. The integer change in the first row of the table alters values without an error, which the guide acknowledges by listing it under type-system changes. Anyone mixing unsigned 64-bit columns with signed arithmetic should diff a pre-upgrade output against a post-upgrade one.
Out-of-core and the speed claim
The other reason to default to streaming is memory. Vink's post says the engine now spills to disk once usage reaches about 80 percent of RAM, with a default disk budget of 64 GB. A query larger than memory can now finish instead of failing, at the cost of disk speed.
The speed claims come from the Polars team's own run, so they are vendor-supplied. The post reports tests on two AWS machines, a c7a.4xlarge with 16 vCPUs and 32 GB of RAM and a c7a.metal with 192 vCPUs and 384 GB, against DuckDB 1.5.6, a DuckDB 2.0 alpha and DataFusion 54.0.0. Each query ran five times with the best run kept and a 60-second timeout. On the smaller machine the post says Polars is "fastest on all but one benchmarks." No independent party is named as having reproduced the TPC-H or TPC-DS figures, and the post does not say which query Polars lost.
Who should wait
The release is out, but a team can pin polars<2 and move when its tests are ready. The lowest-risk path is to run the existing test suite against 2.0 with every join and group-by output compared as a set rather than a list, since any failure that disappears under sorting is a row-order dependency.
The same caution applies to other performance claims The Terminal has covered, such as the Cargo early-metadata change for Rust builds and the TesterArmy e2e project. A changelog's speed figure is a reason to run a team's own benchmark, not a substitute for one.
The next concrete step is the upgrade guide at docs.pola.rs, which lists every change above. Pinning polars<2 keeps the old defaults until a test suite passes.
Sources
More in Software
- 01VB6 Studio Web 0.6.0 Rebuilds Visual Basic 6 in a Browser, Minus COM and OCXWieslaw Soltes's MIT-licensed project reads .vbp project files and exports standalone HTML, but its README rules out the native components that classic VB6 programs lean on.
- 02REA Hands Coding Agents a Disassembler, and 2,963 Stars Followed in a DayThe MIT-licensed toolkit from a developer called morluto wires Ghidra, Hopper and a JavaScript analyser into agents over MCP, and its README pitches rebuilding a feature you have only seen running.
- 03Cloudflare's Web Search API Passes Through Exa, Linkup and Ceramic.ai PricesThe beta, announced Oct. 2 through AI Gateway, adds no markup, so the bill depends on which provider string a developer types and the launch post prints no price.
- 04TesterArmy's e2e Gained 1,398 Stars in a Day. Its Docs Publish No Accuracy FiguresThe Apache-2.0 framework lets an agent drive an app from a plain-English goal, then replays the recorded steps. The one independent benchmark of its decision-model option tested a different job.