LabHub

Blog

Reading the SvelteKit 3.0 Pre-Release — What Breaks, What Tightens, and What Is Still Experimental

한국어English日本語中文

Introduction — No Announcement Post, It Just Showed Up on npm First

There is not yet a "Introducing SvelteKit 3" post on the svelte.dev blog. But the trail on the npm registry is already unmistakable — @sveltejs/kit's 3.0.0-next.0 went up on June 5, 2026, and as of the time of this writing (2026-07-17) the latest pre-release is 3.0.0-next.8 from July 14. Nine pre-releases in under six weeks, running on two tracks side by side with the stable 2.69.3 (July 13).

The repository tells the same story. sveltejs/kit has an open version-3 branch, and the 3.0 milestone shows 107 closed issues and 27 open issues as of today. No stable release date has been announced — so everything in this post should be read as "a snapshot as of next.8." It is a pre-release; things can still change from here.

But read the version-3 branch's changelog straight through from next.0 to next.8 and one thing becomes clear. This major has almost no new features. Instead it settles two years of deprecation notices, raises the toolchain floor, and tightens defaults. And the things the community expects to be the face of SvelteKit 3 — remote functions, await inside components — are still experimental even in the v3 pre-release. Understanding this framing is half the migration decision.

Timeline — Where 2.x Has Already Gotten To

To read v3, you first need the tail end of 2.x. All dates below are the publish timestamps from the npm registry.

2024-12-16  kit 2.12   $app/state added (rune-based — successor to $app/stores)
2025-07-14  svelte 5.36  component await (experimental.async flag)
2025-07-24  kit 2.26   resolve()/asset() added to $app/paths (replaces old base/assets)
2025-07-31  kit 2.27   remote functions (experimental flag)
2026-01-22  svelte 5.48  ← the release that later becomes kit v3's minimum Svelte version
2026-05-01  kit 2.59   query.live added (experimental)
2026-05-22  kit 2.61   query.live becomes an async iterable, query .run() removed (breaking)
2026-06-02  kit 2.62   config can be passed to the Vite plugin without svelte.config.js
2026-06-04  kit 2.63   explicit environment variables (experimental)
2026-06-05  kit 3.0.0-next.0  ← pre-release begins
2026-07-14  kit 3.0.0-next.8  ← current

Two things stand out. First, 2.62 and 2.63 are the "trailers" that shipped right before v3 — in the words of the July digest, moving config into vite.config and explicit environment variables both landed in 2.x first as a "preview of how this will work in Kit 3." Second, as 2.61 shows, features tagged experimental keep taking breaking changes even in minor releases. Removing .run(), changing the requested(...) signature — these shipped as semver minors. If you turned the flag on, you stepped outside the zone semver protects.

The Floor v3 Raises — Minimum Runtime and Toolchain

These are the minimum requirements pinned down by next.0's changelog.

The changelog cites "faster builds through Vite hook filters and stronger adapters that use the Vite environment API" as the rationale for the Vite 8 requirement — no concrete build-time figures have been published anywhere, so I'll only note here that this is the project's own framing.

APIs Being Removed — Settling Two Years of Deprecation Notices

These are the things removed or renamed in v3. In every case a successor API already shipped in 2.x first, so there is effectively no "sudden removal."

Going awaySuccessorWhen the successor landed
the entire $app/stores module (#15499)$app/statekit 2.12 (2024-12)
base/assets/resolveRoute from $app/paths (#15507)resolve()/asset()kit 2.26 (2025-07)
invalidateAll (deprecated) (#16289)refreshAll (also applies to the goto option)newly introduced in v3 next.8
$app/environmentrenamed to $app/env (alias kept, next.1)v3
the four $env/* modulesexplicit environment variables ($app/env/private/$app/env/public)kit 2.63 (experimental)
svelte.config.js requiredpass config to the Vite plugin (#16007)possible since kit 2.62
param files inside a foldera single params.js/ts file (#16189)v3
the preloadStrategy optionalways modulepreload + output.linkHeaderPreloadv3
CSRF checkOrigintrustedOriginsalready deprecated within kit 2.x
@sveltejs/kit/node/polyfills, createEntries for adaptersnone (removed)

A few points worth flagging.

Removing $app/stores is the final period on the rune transition. Svelte 5 runes pushed stores out long ago, but SvelteKit's page/navigating/updated stores stayed alive for backward compatibility. Its successor $app/state has now had a year and a half out in the world, so as retirements go, this one is on the gentle side.

invalidateAllrefreshAll is a vocabulary unification. Read PR #16289 and the intent is clear — in the world of remote functions, refreshing data is query.refresh(), and that vocabulary had drifted apart from "invalidation" in the world of load functions. refreshAll is the name that folds both into one word, and the option to always rerun load functions was cleaned up alongside it. One thing to note: refreshAll does not exist in 2.69.3. It's something you switch to when you move up to v3, not something you can do today.

Environment variables move from module magic to explicit declaration. The docs' preview language is unambiguous — explicit environment variables become the default in v3, and the $env/* modules and $app/environment are removed. The new approach is declared in src/env.ts.

// src/env.ts — you can try this early on kit 2.63+ via experimental.explicitEnvironmentVariables
import { defineEnvVars } from '@sveltejs/kit/hooks';

export const variables = defineEnvVars({
	API_KEY: {}, // private by default — importable only from $app/env/private
});

Where $env/static/private used to be the clever trick of "enforcing exposure by way of import location," the new approach pins down the entire list of environment variables that exist in the app, with types, in a single file. The problem of not being able to tell what variables exist just by reading the code goes away — in exchange, every new variable means one more line of declaration.

Defaults Changing Quietly — Mostly on the Security Side

These are quieter than removals, but they actually change behavior. This is usually where migration time gets eaten.

For what it's worth, the fix that forces cache-control: private, no-store on remote function responses — so personalized query results don't stick around in a shared cache — already landed in 2.65.2, not v3. Tightening security defaults isn't a v3-only theme; it's been the consistent direction of the last several months.

What's Still Experimental — v3 Is Not a Feature Major

This is the most important section of this post.

Remote functions are still experimental even in v3. The official docs still say "currently experimental… subject to change without notice," and require two flags: kit.experimental.remoteFunctions and compilerOptions.experimental.async. What's more telling is the direction of the v3 pre-releases — next.7 actually banned putting *.remote.ts/js files in place without the flag (#16247, merged 2026-07-07). That is not a change you'd make if stabilization were imminent. Nearly a year after shipping as 2.27 in July 2025, and even past the v3 major, there is no API stability guarantee for remote functions.

Component await is the same story. It's been usable behind the experimental.async flag since Svelte 5.36 (2025-07-14), and the docs spell out exactly when the flag comes off — "The experimental flag will be removed in Svelte 6." And Svelte 6 does not exist on npm — no 6.x has ever shipped, stable or pre-release, and svelte's latest is 5.56.6 (2026-07-16). The fact that kit v3's minimum requirement is Svelte 5.48 sums up this framing: SvelteKit's major version and Svelte's major version are separate trains. The compiler side's experimental list also still holds the fork API (5.42) and async SSR (5.39).

There is one graduation running the other direction — OpenTelemetry tracing left the experimental namespace and became a stable API in next.7 (#16260).

To sum up, this is what v3 actually is: every feature that's generating buzz is shipping simultaneously to both 2.x and v3 on the experimental track, and the major version is spent swapping out the floor underneath — runtime, bundler, names, defaults. The expectation that "remote functions will stabilize once you move to v3" does not hold up against the current evidence.

A Contrast With the Neighborhood — Majors Do Different Jobs

It's an interesting contrast that the news that lit up the React ecosystem the same week was the Rust port of the React Compiler. React is building new compiler infrastructure from scratch to eliminate manual memoization — and that work is still at an experimental WIP stage — while Svelte has had a compiler as its foundation from day one, so it never had that stage to go through. Instead, Svelte's major is spent raising the bundler (rolldown) and runtime floor. Both frameworks share a common thread in 2026: spending major-version-level energy on foundation work rather than a "big feature dump," and neither one is about to substantially change an app developer's code anytime soon.

So What Should You Do Right Now

What you can do today, on 2.x, ahead of time — all of it is prepayment toward the v3 migration.

What you shouldn't do.

If you're an adapter or library author there's more work ahead. createEntries is gone, adapters will be able to supply Vite plugins directly (#16206), and adapters are being reorganized around the Vite environment API. That ecosystem, more than app code, is the likelier practical bottleneck at v3's release.

Closing

The changelog for the SvelteKit 3.0 pre-release isn't flashy. And I think that's a good sign. This isn't the kind of major that demands relearning — a swapped-out router, a changed data-loading model — it's a major that pays off deprecation notices, raises the floor, and tightens defaults. You don't have to relearn runes, and you don't have to rewrite your load functions.

What you do need to get exactly right is expectations. Remote functions and component await becoming "official" is not an event that happens at SvelteKit 3 — the former has no timeline yet, and the latter is, per the docs, Svelte 6's job. The reading that lines up with the changelog is that v3 is the release laying the floor that future stands on (a rolldown-based Vite 8, Node 22, a cleaned-up API surface). Since the pre-release is still in progress, some of the details in this post may have changed by the stable release — this is written as a snapshot on the premise that it'll be checked again then.

References

Comments

No comments yet.

Sign in to leave a comment