Polars 1.44 (26 Aug 2026, Thijs Nieuwdorp) adds sink_iceberg schema_mode=merge, an adaptive S3/GCS/Azure rate limiter, correlated SQL subqueries, and selective when/then speedups. Three things to try tonight. Not a pandas bake-off. Not investment advice.
Polars 1.44 was announced on 26 August 2026 by Thijs Nieuwdorp. The same day, GitHub also tagged py-1.44.1. This note is “what last week’s release changed” plus three things to try tonight if you already scan Parquet or write a bit of pl.sql. It is not a pandas Copy-on-Write vs Polars rewrite, not a speed league table, and not investment advice.
The only course CTA is Introduction to Python Programming. Related Hub: LightGBM 4.7 native Polars, DuckDB 2.0 laptop SQL, and last week’s statsmodels 0.15 if you convert Polars to pandas at a model boundary.
From the official post:
sink_iceberg(..., schema_mode="merge") — Iceberg schema evolution on write (PR #28794). Match columns by name and add missing ones. Without it, an extra column raises SchemaError. schema_mode="overwrite" requires mode="overwrite". snapshot_properties (#28793) attach key-value metadata to the commit. Native scan_iceberg now reads v3 deletion vectors (#28772) without falling back to PyIceberg.
Adaptive rate limiter for S3 / GCS / Azure (#28591, #28885). One limiter per object store, separate for reads and writes. AIMD: raise the rate while requests succeed, cut it on 429/503. Defaults: init 1,000 req/s, floor 10, ceiling 50,000. Tune with integer storage_options keys rate_read_init / rate_read_floor / rate_read_ceiling (and rate_write_*). Retries: 2→8 attempts, initial backoff 100→250 ms, max backoff 15s→5 s, timeout 10s→30 s. A 429 in logs is probing, not automatically a failed query.
Correlated SQL subqueries (#28494 and follow-ups). 1.43 raised SQLSyntaxError for salary > (SELECT AVG(...) WHERE x.dept = employees.dept). 1.44 decorrelates that shape, plus EXISTS / correlated IN, function visibility inside subqueries, and ANY/ALL desugaring (= ANY → IN). Not everything is supported: some ANY/ALL + correlated operator combinations still raise SQLInterfaceError.
when/then/otherwise only evaluates rows it keeps (#28498). On a 5,000,000-row example with a regex in then: about 6.10× at 5% selectivity, 1.53× at 50%, unchanged at 100%. Filter rechunking and Parquet/streaming planner work are free if you upgrade.
Deprecations (read, do not panic): rechunk on scan/read and Expr.rechunk(); struct.rename_fields() length mismatch now warns.
python -c "import polars as pl; print(pl.__version__)"
# pip install -U "polars==1.44.1"
1. Selective when/then (no cloud account needed).
import numpy as np
import polars as pl
N = 200_000 # laptop-sized; blog used 5_000_000
rng = np.random.default_rng(0)
df = pl.DataFrame({
"flag": rng.random(N) < 0.05,
"text": ["abc-12345-xyz"] * N,
})
out = df.select(
pl.when(pl.col("flag"))
.then(pl.col("text").str.extract(r"-(\d+)-", 1).cast(pl.Int64))
.otherwise(0)
.alias("code")
)
print(out.head(3))
2. Correlated SQL on a tiny employee frame (from the 1.44 post):
import polars as pl
employees = pl.LazyFrame({
"name": ["Alice", "Bob", "Carol", "Dan", "Erin"],
"dept": ["eng", "eng", "sales", "sales", "sales"],
"salary": [120, 95, 80, 110, 90],
})
print(pl.sql("""
SELECT name, dept, salary
FROM employees
WHERE salary > (
SELECT AVG(x.salary) FROM employees AS x WHERE x.dept = employees.dept
)
ORDER BY name
""").collect())
3. Iceberg merge or cloud limiter — pick one. If you already have an Iceberg table, append with schema_mode="merge" as in the blog snippet. If you scan s3://.../**/*.parquet and still fail on throttling, lower the ceiling:
# lf = pl.scan_parquet(
# "s3://my-bucket/data/**/*.parquet",
# storage_options={"rate_read_init": 500, "rate_read_ceiling": 5_000},
# )
Stop after one of these three. Full notes: py-1.44.0 and py-1.44.1.
If Python environments still fight you, use Introduction to Python Programming after work, then print polars.__version__ and run one of the three sketches.