Windows Developer Blog posted on October 14. Chris Anderson, Distinguished Engineer. Python 3.15 makes native Windows on Arm the default runtime on those machines. Native CPython builds existed before. What changed is maturity: WoA is a regular CPython target, Tier 2 means platform failures get fixed or the change reverts, and the installer stops surprising you with x64.
A September 2026 scan of the 1,000 most-downloaded PyPI projects: about 94% of latest releases ship a native Windows on Arm wheel or a platform-independent wheel. Anaconda’s main channel has more than 2,500 packages for WoA. GitHub Actions hosted runners: windows-11-arm and windows-11-vs2026-arm. x64 packages still run through Windows emulation.
That is an installer story. It is not your FastAPI image.
Zenn on October 16 is a 3.15 vs 3.14 log on Windows 11 with uv 0.10.3. python -VV there is Python 3.15.0 (main, Oct 9 2026, 15:33:25) [MSC v.1951 64 bit (AMD64)]. AMD64. Lazy imports and UTF-8 as default are real 3.15 changes. They are not an Arm test. Do not paste that scrap into a Snapdragon laptop runbook.
We already filed 3.15.0 after RC3 and lazy imports against FastAPI startup. This week the default architecture moved.
Default native is the installer, not pip
Anderson’s post is careful. Native WoA CPython has been around for several versions. 3.15 is when the default on an Arm Windows device is the native runtime, and when CPython’s own policy treats the platform as Tier 2. Failures on that target are supposed to get fixed or reverted. That is a CPython process change. pip will still install whatever wheel matches the tags it sees.
If you upgraded in place from an x64 3.14, you may still be on an x64 interpreter until you install the Arm64 build. “3.15 is native by default” is about new installs on WoA hardware. Check python -VV. If it says AMD64 on a Snapdragon box, you are in emulation and this post is not about you yet.
Platform-independent wheels are most of that 94%. Pure Python FastAPI itself was never the problem. The problem is the compiled stack next to it: pydantic-core, orjson, httptools, watchfiles, any native crypto. 94% of top 1,000 is not 94% of your lockfile.
Anaconda’s 2,500+ figure is conda, not PyPI. If your web app is pip-only, do not quote Anaconda as coverage. If you already live on conda-forge, it is a second inventory.
Emulation is still the escape hatch. Anderson says apps that still need x64 packages can run that way while those projects add Arm wheels. Escape hatches are slow. Do not ship a latency-sensitive uvicorn worker and then discover it is x64-on-Arm.
94% is a PyPI scan
The 94% line is “latest releases of the 1,000 most-downloaded projects,” September 2026, native WoA wheel or any-platform wheel. It is availability, not “we ran your test suite.” Anderson says that out loud. Compatibility of an application is a different measurement.
Top 1,000 is popularity. Your internal private index is not in it. The one C extension you vendored in 2019 is not in it. numpy might be fine and the random crc32c wheel from 2022 might not.
Zenn’s table is useful as a reminder that even on AMD64, 3.15 is uneven. torch 2.14.1 was not on PyPI; it came from PyTorch’s index with a cp315 wheel. tensorflow 2.21.0 and tf-nightly 2.23.0.dev20261014 were missing. onnxruntime 1.31.0 dated October 9 was there. duckdb 1.5.6 was there. PyYAML 6.0.3 built from source without libyaml, so no CSafeLoader. That log is AMD64. Arm will be stricter, not looser, for anything that needs a compiler.
3.10 hit EOL on October 1, 2026, in that same scrap. If your FastAPI image is still 3.10, the WoA default is not your problem. The clock is.
Do not read 94% as “pip install fastapi uvicorn[standard] will be native.” uvicorn[standard] pulls httptools and, on Unix, uvloop. uvloop is not a Windows story. httptools is. Check the wheel tags.
GitHub already has the runner
windows-11-arm and windows-11-vs2026-arm are hosted runners for eligible public and private repos. Anderson says CPython uses this infrastructure for its own native Arm64 Windows jobs. Package authors can build wheels and do a clean-install test without self-hosted Arm boxes.
Before those runners, you needed your own hardware or emulation. That barrier is why a lot of projects never published win_arm64 wheels. The barrier is lower. It is not gone. “Eligible” still means you have to be allowed to use the runner.
If you maintain a FastAPI service that developers run on Windows laptops, add a job. runs-on: windows-11-arm. Install 3.15. pip install -r requirements.txt. Start uvicorn. Hit /health. That is the test the 94% scan does not run.
If you only CI on ubuntu-latest, you will not see the missing wheel until a new hire with a Snapdragon laptop files it. The runner is cheaper than that ticket.
vs2026 in the runner name is a toolchain flag. If your extension builds with MSVC, use the runner that matches the compiler you claim to support. Do not assume windows-11-arm and windows-11-vs2026-arm are interchangeable without reading GitHub’s current image docs.
CPython eating its own dogfood on that runner is the credibility. Your job is to eat yours.
FastAPI’s native edges
FastAPI the package is typing plus Starlette plus Pydantic. Pydantic v2 is pydantic-core in Rust. That wheel is the one that has to exist for win_arm64. orjson is optional and native. httptools is optional and native. watchfiles is native. If you pin uvicorn[standard] plus orjson plus pydantic>=2, you have three compiled reasons to fail on a new interpreter.
Cloudflare Python Workers already taught a related lesson: the server that runs your app may not be the server you develop on. WoA laptops are a third machine class next to Linux prod and macOS. Three classes means three wheel tags.
Do not enable uvloop on Windows. It was never the Windows extra. Do not copy a Linux Dockerfile FROM python:3.15 and assume the same pins work on Arm Windows. Linux aarch64 and Windows arm64 are different wheels.
If you ship a Windows desktop wrapper around a local FastAPI process, 3.15’s default native runtime is exactly your support queue. Print sys.version and sys.platform plus platform.machine() in /health. When someone files “it’s slow,” you want to know if they are emulating.
UTF-8 default, from the Zenn 3.15 log, will bite Japanese Windows paths and some subprocess calls. That is a 3.15 behavior change on every arch. Fix it in the same PR as the Arm wheel, or you will blame Arm for a Unicode bug.
Lazy imports can hide a missing native module until a request hits that path. A FastAPI app that boots and then explodes on the first orjson response is worse than a pip failure. Import the native extras at startup in CI.
What to put in CI this week
Matrix: ubuntu-latest, windows-latest, windows-11-arm if you have access. Python 3.15. Install from the same lockfile you ship. Fail on a missing wheel, not on a fallback compile, unless you actually want to compile.
Pin wheels with hashes. If pip compiles pydantic-core on an Arm laptop because the wheel is missing, the build will ask for Rust and then become a blog post.
Keep x64 emulation as a documented exception, not as the unstated default. If a dependency has no Arm wheel, pin that fact in the README and set the job to x64 until it does. Silent emulation is how a 200ms p99 becomes 600ms on one employee’s machine.
Do not treat Anderson’s 94% as a green check. Treat it as permission to try. Run the try on the runner CPython already uses. If FastAPI starts, hit a route that uses pydantic and orjson. If it does not start, the missing wheel is the ticket, not “Windows on Arm is not ready.” The blog post says it is ready enough for mainstream work. Your lockfile is the remaining argument.
Tier 2, in Anderson’s wording, means platform failures get fixed or the responsible changes revert. That is CPython’s bar. It is not uvicorn’s bar. If uvicorn ships a Windows-only bug on Arm, you wait on uvicorn. Put the version pin in the ticket.
windows-11-arm vs windows-latest is x64 vs Arm, not “Windows vs Windows.” A green windows-latest job does not bless a Snapdragon laptop. Name the arch in the CI badge so humans stop assuming it does.
Clean-install tests, in Anderson’s post, are the point of the hosted runner. Build the wheel, then install it into a fresh environment, then run the suite. Compiling on a dirty developer laptop hides missing Visual C++ redistributables and missing Rust. FastAPI does not need Rust. pydantic-core does.
CPython’s own Arm64 Windows jobs on that runner are the existence proof. If CPython can fail a PR because WoA broke, your web app can fail a PR because orjson did not publish win_arm64 for 3.15. Copy the idea, not the CPython makefile.
Zenn compared 3.11 through 3.15 on NuGet’s python packages, AMD64, JIT off, pyperformance --fast. That is a speed log on Intel/AMD Windows. It does not tell you whether httptools installs on Snapdragon. Do not quote a geometric mean you did not rerun on Arm. Quote the method: same pins, same tests, other arch.
torch on PyTorch’s extra index, not PyPI, is the pattern a lot of ML-adjacent FastAPI services copy. If your /predict route imports torch, WoA support is whatever PyTorch published for cp315 and that arch. Anderson’s top-1,000 PyPI scan will not see an extra index. Add that extra index to CI or admit the laptop cannot run /predict natively.
UTF-8 default plus Windows console plus subprocess is a second ticket. If you spawn ruff or alembic from FastAPI’s startup, test that spawn on 3.15 before you blame Arm. The Zenn log is there because Japanese Windows is where UTF-8 default shows up first.
Workers and laptops are different. Cloudflare’s Python Workers still do not care what your Surface ran. Linux prod still does not care. The only machine that cares is the one your teammate bought this quarter. Put that machine in the matrix or keep a loaner x64 around. Those are operational choices. The October 14 post just removed the excuse that native Python on WoA was experimental.
3.15 picked native Arm on the way in. Production Linux did not move. The laptop did. Match the laptop in CI or keep buying time with emulation. Those are the two options. A press post is not a wheel.
Discussion
Leave a comment
No comments yet
Be the first to start the conversation.