Build1 distinct publisher3 min readPublished
Ritchie Vink is selling 2.0 as a boring upgrade. Mostly it is, but engine="auto" now resolves to streaming by default, so joins and group_bys stop carrying incidental row order, and pipelines that leaned on it will drift quietly.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Batching is the mechanism behind the speedup, and it comes with a behavioural cost. The streaming engine cuts a query into pieces instead of keeping the whole dataset and its intermediate results resident, which is what buys execution over data larger than RAM [4]. Nothing in that model carries the input's incidental ordering through a join, a group_by or an unpivot, so the values arrive correct and the sequence does not match what you had [5]. Polars' migration guide gives two answers: sort explicitly, or ask for observable order with settings such as `maintain_order="left"` [6]. There is also a one-line retreat, `pl.Config.set_engine_affinity("in-memory")`, which pins the old engine globally, and the same choice can be made per query [7].
On speed, Polars says the streaming engine should be about five times faster in aggregate, and is clear that the figure comes from its own benchmarks rather than independent testing [8]. Set that against the published per-scale numbers and the aggregate claim is exactly twice the small-scale result: 5 divided by 2.5 [16]. So the headline multiple sits near the SF100 end of the range, not the SF10 end [9]. For it to transfer you need a query mix that resembles PDS-H, data volumes closer to SF100 than SF10, and comparable hardware. Polars itself notes that PDS-H is derived from TPC-H without being audited or compliant, and that results vary by query and by machine [10].
The strictness changes are easier to plan for, because they fail loudly. Horizontal concatenation of unequal-height frames now raises `ShapeError` instead of padding the shorter one with nulls, and `horizontal_extend` is there if padding was the intent [13]. Ambiguous string-to-date casts are gone in favour of dedicated parsers such as `str.to_date()`, and removed methods and arguments increasingly raise `AttributeRemovedError` or `ArgumentRemovedError` with a pointer to the replacement [14]. The `is_in` case is the one worth reading twice: exact integer representation in a 64-bit float runs out at 9,007,199,254,740,992 [17], and above that a user ID could round into its neighbour and match the wrong person [12]. Two customers quietly becoming one customer is a memorable way to lose a row.
That asymmetry is the whole migration plan. Type and shape changes announce themselves with an error and a line number pointing at the fix. An ordering assumption that nobody wrote down leaves nothing to grep for.
This fits the direction Vink has been pushing all along. Vink tried copying pandas' API early on and said in a 2024 interview that it clashed with his preference for predictable output types and stricter contracts [20], and the major version exists precisely to remove old design decisions and change defaults that were constraining the query engine [18]. In my context, where batch outputs get sorted before they are written anyway, the explicit sort is cheap and the engine pin is not: pinning keeps you on the path upstream is walking away from. If you cannot afford the sort today, pin it, but treat that as a dated stopgap rather than a setting.
Ranked by verification strength, evidence, and original report placement.
Polars creator Ritchie Vink released the first release candidate for Polars 2.0 on September 2nd, making the library's streaming engine the default for lazy queries.
Vink said he hopes the upgrade will be a "boring experience" because 2.0 carries few marquee features.
Calling collect() on a Polars LazyFrame previously resolved to the in-memory engine unless the developer explicitly selected streaming; in 2.0 the existing engine="auto" setting resolves to streaming instead.
Streaming divides a query into batches rather than requiring the complete dataset and intermediate results to remain in memory, letting Polars process datasets larger than available RAM and improving performance on supported operations.
Streaming does not preserve incidental row order for operations such as joins, group_by and unpivot; a pipeline that assumes a left join retains the left DataFrame's existing order may produce differently ordered rows after the upgrade even when values remain correct.
Polars' 2.0 migration guide tells developers to sort explicitly or request observable order through settings such as maintain_order="left".
Distinct publishers with included, body-backed reporting in this cluster.
runtimewire.com
1 article · September 3, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Pytest catches the pipeline bugs that ship as wrong numbers1 distinct publisher
build
SGLang's one-GPU Qwen3.8-27B recipe is the useful half of the release1 distinct publisher
build
Pandex hooked a Fortune 500 agent four minutes after claiming a package name from llms.txt1 distinct publisher
science
TeamPCP hid its infostealer inside the scanners that audit everyone else's code1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Verifiable mechanics, unverifiable speed
The behavioural core of this story is unusually checkable for single-outlet reporting: engine="auto", maintain_order="left", the InvalidOperationError on is_in, the ShapeError on horizontal concatenation — a developer can confirm every one of them against 2.0.0rc1 and the migration guide in an afternoon, which is why we score it well above the usual one-source floor. The speed is a different matter. 2.5x at SF10, 6.4x at SF100, five-ish in aggregate: all run by Polars, on a suite Polars itself says is not audited TPC-H.
Candidate on PyPI, nobody running it yet
Nothing here shows 2.0 in production. The artefact is a release candidate with a final version promised in unspecified 'several weeks'. The 775 million downloads and 39,000 stars belong to the library's history, not this release; they measure how many installations the default change will eventually reach, which is a very different quantity from how many teams have taken it.
Two errors, opposite directions, one cancels less
Vink undersells: 'boring experience' is a strange label for a change that can silently reorder join output in a pipeline nobody has touched. The fivefold figure oversells in the other direction, sitting at double the SF10 measurement and hugging the SF100 run, so a team benchmarking its own middling-sized data may wonder where the promised speedup went. Net slightly overstated — not because the engineering is oversold, but because the single quantity on offer is the promotional one.
The free default now matches the paid engine
Runtime Wire earns credit for putting this last section in rather than burying it: Polars the company took roughly $4 million from Bain Capital Ventures and roughly $21 million from Accel, sells Polars Cloud and an on-premises distributed engine on the same API, and has just made the local default the execution model those products are built around. The benchmarks are its own, the download and star counters are its own homepage, and the AI-agent angle arrives precisely when that angle sells. None of which makes the design wrong — the argument against silent coercion predates coding agents — but every favourable number in this story has the same author.
Sure of the shape, unsure of the bill
We are confident about what changes and confident it will not be noisy about changing; we are much less confident about magnitude and timing. One publisher, no third-party timing, a release that is not final, and a migration guide that admits its own removal exceptions are incompletely covered. So the upgrade's contours are clear while its cost to any particular codebase remains an open question until teams start reporting back.