{
    "archive_path": "archive/1788430023.254921",
    "base_url": "pola.rs/posts/announcing-polars-2",
    "basename": "",
    "bookmarked_date": "2026-09-03 10:07",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/pola.rs/posts/announcing-polars-2",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=pola.rs",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": "pola.rs/posts/announcing-polars-2/index.html"
    },
    "domain": "pola.rs",
    "extension": "",
    "hash": "RV2W9093073ZA223D2KA",
    "history": {
        "archive_org": [],
        "dom": [],
        "favicon": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=pola.rs"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-03T10:10:06.820522+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1788430023.254921",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-03T10:10:06.442965+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://pola.rs/posts/announcing-polars-2/"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-03T10:10:07.146501+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1788430023.254921",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-03T10:10:06.838395+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [],
        "media": [],
        "mercury": [
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://pola.rs/posts/announcing-polars-2/"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-09-03T10:10:14.924361+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1788430023.254921",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-03T10:10:11.119139+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [],
        "readability": [
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmpuf4_qnay",
                    "https://pola.rs/posts/announcing-polars-2/"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-09-03T10:10:11.111882+00:00",
                "index_texts": [
                    "Back to blog\n Pre-release of Polars 2.0 By Ritchie Vink on Wed, 2 Sept 2026  Today we are releasing the first release candidate for Polars 2.0. The definite 2.0 release will land in the following weeks. We don\u2019t aim to make a big feature release of Polars 2.0. In fact we hope it to be a boring experience for you. The reason we bump this major version is that we can get rid of design decisions made in the past that currently block us and then we want to change defaults to more sensible settings that will benefit a greater audience. The biggest default change will be that all LazyFrame queries now will run on the streaming engine. Casual Polars users can therefore expect huge improvements in memory usage and performance. In aggregate we expect the streaming engine to be easily 5x faster.\nTo help users transition to 2.0, we have posted a full migration guide. This post will cover a few of the highlights.\nStreaming engine as default\nThis is the biggest impact change of 2.0. Calling collect on a LazyFrame will now default to the streaming engine, leading to massive memory and performance improvements on most queries for users. The reason this required a major version bump is that the streaming engine doesn\u2019t guarantee row-order by default for certain operations (join, group_by, unpivot, etc.). If you require observable row-order in those operations, you can opt in to that by setting maintain_order=True.\nFor users who want to keep using the \u201cin-memory\u201d engine as default, they can do so by setting the engine affinity.\nlf = pl.LazyFrame({\"k\": [2, 1, 0], \"v\": [\"a\", \"b\", \"c\"]})\nother = pl.LazyFrame({\"k\": [0, 1, 2], \"r\": [\"x\", \"y\", \"z\"]})\n\n# 2.0: engine=\"auto\" now resolves to the streaming engine.\n# Row order is no longer guaranteed for joins, group_by, unpivot, ...\n(\n    lf\n    .join(other, on=\"k\", how=\"left\")\n    .collect()\n)\n# \u250c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2510\n# \u2502 k   \u2506 v   \u2506 r   \u2502   <- order may not match `lf`'s original row order\n# \u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2518\n\n# Opt in to observable order for this query:\n(\n    lf\n    .join(other, on=\"k\", how=\"left\", maintain_order=\"left\")\n    .collect()\n)\n\n# Or keep the old in-memory engine as the default, process-wide:\npl.Config.set_engine_affinity(\"in-memory\")\n\n# ...or per query:\n(\n    lf\n    .join(other, on=\"k\", how=\"left\")\n    .collect(engine=\"in-memory\")\n)\nStricter Polars\nPolars aims to be strict and fail fast. Errors should ideally raise up-front, not 20 minutes into a pipeline. Implicit behavior on data-mismatches should be opt-in, not a default, since those mismatches can hide bugs. This strictness has become even more valuable with the rise of AI-driven development. Agents can validate a query\u2019s structure early by calling collect_schema(), which resolves types and catches schema-level mismatches without materializing any data. This ensures fast feedback for the agents, meaning they can iterate faster. Not all errors can be caught during compilation of the query plan, some depend on data. In these cases Polars defaults to stricter behavior to ensure inconsistencies are caught instead of silently producing different results.\nBelow are a few examples where Polars has gotten more strict:\nis_in lossless type-coercion\nIf you run an is_in expression on different data-types, Polars used to cast both types to their common supertype, even if that conversion was lossy\nBelow is an example with user-ids that can go wrong by silent data-type mismatches.\n# Checking if a user ID matches a list of \"flagged\" account IDs\n# (flagged_ids loaded from a JSON export, where large IDs became floats)\nflagged_ids = pl.Series([9007199254740992.0])\nuser_id = pl.Series([9007199254740993])  # Int64 -> a different ID, off by 1\nuser_id.is_in(flagged_ids)\nBefore 2.0, user_id gets coerced to Float64 to match flagged_ids. But 9007199254740993 sits above 2^53 (9007199254740992), the largest integer float64 can represent exactly, so it silently rounds down to 9007199254740992.0, giving a false positive.\nIn 2.0 this raises: InvalidOperationError: 'is_in' cannot check for Int64 values in List(Float64) data., users should explicitly cast to deal with lossy type conversion.\nStrict concatenation\nHorizontal concat will now check lengths instead of silently filling with null.\n# Joining per-day transaction counts with per-day fraud-flag counts,\ntransactions = pl.DataFrame({\"day\": [1, 2, 3, 4, 5], \"count\": [120, 98, 143, 87, 156]})\n\n# Upstream job for day 5 failed silently\nfraud_flags = pl.DataFrame({\"flagged\": [2, 0, 5, 1]})  # only 4 rows\n\npl.concat([transactions, fraud_flags], how=\"horizontal\")\nshape: (5, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 day \u2506 count \u2506 flagged \u2502\n\u2502 1   \u2506 120   \u2506 2       \u2502\n\u2502 2   \u2506 98    \u2506 0       \u2502\n\u2502 3   \u2506 143   \u2506 5       \u2502\n\u2502 4   \u2506 87    \u2506 1       \u2502\n\u2502 5   \u2506 156   \u2506 null    \u2502  <- day 5 silently has no flag count\n\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\nIn 2.0 this will raise with:\nShapeError: cannot concat dataframes with different heights in 'strict' mode\nIf padding is what you wanted, you have to explicitly opt-in to that with how=\"horizontal_extend\". Making that intention clear to the reader.\nRemoval of casts in favor of dedicated methods/constructors\nAnother one worth mentioning is the removal of many casts that were ambiguous or should be applied via their dedicated parsing expression, leading to one obvious way to parse data.\nEnums/Categoricals <> integers.\npl.Series([None, 1, 0, 2], dtype=pl.UInt32).cast(pl.Enum([\"a\", \"b\", \"c\"]))\n# ComputeError: casting from u32 to enum is not supported.\nUse instead: .cat.to(dtype) for int \u2192 categorical, .cat.physical() for categorical \u2192 int.\nParsing Strings to temporal data-types\npl.Series([\"2022-08-30\"]).cast(pl.Date)\n# InvalidOperationError: casting from string to date is not supported.\nUse instead: .str.to_date() / .str.to_datetime(). These allow you to apply a parsing format, giving you more control over how the data is parsed.\nThese were just a few examples, but we landed many more strictness improvements. See them all in the migration guide.\nRaising informative errors\nWe put a lot of effort into making sure you as user or your agent can continue if you used old parameters that are not supported anymore. We added two new typed exceptions for this; polars.exceptions.AttributeRemovedError and polars.exceptions.ArgumentRemovedError that handle removed attributes and methods and removed parameters respectively.\nThe error messages should point you to the new API instead. Below we show two examples.\n>>> lf.melt(id_vars=\"a\", value_vars=\"b\")\npolars.exceptions.AttributeRemovedError: `melt` was removed in version 2.0;\nuse `LazyFrame.unpivot` instead, with `index` instead of `id_vars`\nand `on` instead of `value_vars`\n>>> df.join(df, on=\"a\", join_nulls=True)\npolars.exceptions.ArgumentRemovedError: the argument 'join_nulls' for\n'DataFrame.join' was deprecated in version 1.24 and has been removed\nin 2.0.0. It was renamed to 'nulls_equal' in version 2.0.\nMost of the removed functionality has been deprecated for a long time and hopefully should not have affected your pipelines if you have stayed up to date. Reach out to us if you think we should have kept some functionality you relied on.\nLast words\nPolars 2.0 is about better defaults (most importantly the streaming engine) and a better API. We hope this release is rather boring. We don\u2019t gate new features behind major version bumps as we ship them as soon as their ready.\nDon\u2019t be mistaken, Polars 2.x will be much better than 1.x. There is a lot in flight that we haven\u2019t talked publicly enough: proper out-of-core support for the streaming engine, a new IO-plugin design, what we think will be the fastest S3 reader out there, major SQL coverage improvements, a cost-based planner, join reordering, and the removal of mmap, which will make our pipelines fully async end to end.\nTry the release candidate by installing pip install polars==2.0rc1. Give it a spin and reach out to us here: https://github.com/pola-rs/polars/issues or contact us on discord: https://discord.gg/4UfP5cfBE7."
                ],
                "output": "readability",
                "pwd": "/data/archive/1788430023.254921",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-03T10:10:09.282242+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [],
        "singlefile": [],
        "title": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://pola.rs/posts/announcing-polars-2/"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-03T10:10:09.277676+00:00",
                "index_texts": null,
                "output": "Polars \u2014 Pre-release of Polars 2.0",
                "pwd": "/data/archive/1788430023.254921",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-03T10:10:09.252276+00:00",
                "status": "succeeded"
            }
        ],
        "wget": [
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--backup-converted",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--timeout=120",
                    "--restrict-file-names=windows",
                    "--warc-file=/data/archive/1788430023.254921/warc/1788430207",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "https://pola.rs/posts/announcing-polars-2/"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-09-03T10:10:09.246550+00:00",
                "index_texts": null,
                "output": "pola.rs/posts/announcing-polars-2/index.html",
                "pwd": "/data/archive/1788430023.254921",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-03T10:10:07.154476+00:00",
                "status": "succeeded"
            }
        ]
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": null,
        "dom": null,
        "favicon": "favicon.ico",
        "git": null,
        "media": null,
        "pdf": null,
        "screenshot": null,
        "singlefile": null,
        "title": "Polars \u2014 Pre-release of Polars 2.0",
        "warc": null,
        "wget": "pola.rs/posts/announcing-polars-2/index.html"
    },
    "link_dir": "/data/archive/1788430023.254921",
    "newest_archive_date": "2026-09-03T10:10:11.119139+00:00",
    "num_failures": 0,
    "num_outputs": 6,
    "oldest_archive_date": "2026-09-03T10:10:06.442965+00:00",
    "path": "/posts/announcing-polars-2/",
    "schema": "Link",
    "scheme": "https",
    "snapshot_id": "72228975-88c9-4ee4-8308-283dfbce2129",
    "sources": [
        "/data/sources/1788430023-import.txt"
    ],
    "tags": null,
    "tags_str": "",
    "timestamp": "1788430023.254921",
    "title": "Polars \u2014 Pre-release of Polars 2.0",
    "updated": "2026-09-03T10:10:06.442533+00:00",
    "updated_date": "2026-09-03 10:10",
    "url": "https://pola.rs/posts/announcing-polars-2/"
}