SvelteKit 3 Migration: The Breaking Changes You Need to Check
SvelteKit 3 changes configuration, dependencies, imports, navigation, cookies, redirects, and adapters. Here is what existing SvelteKit 2 projects should check before upgrading.
On this page
SvelteKit 3 arrived on October 1 with a migration command that can handle much of the mechanical upgrade, but it is not a one-command version bump. The release changes where framework configuration lives, raises the minimum Node.js and TypeScript versions, replaces the familiar $lib alias, removes several older APIs, and changes behavior around navigation, cookies, forms, and external redirects. For an existing SvelteKit application, the real task is reviewing those behavioral changes after the automated migration has finished.
SvelteKit 3 migration starts with a newer toolchain
SvelteKit 3 requires Node.js 22.17 or newer, TypeScript 6, Svelte 5.57.1 or newer, Vite 8.0.12 or newer, and version 7 of the Svelte Vite plugin. That is a significant baseline change because an application can be perfectly healthy on SvelteKit 2 and still fail before its own code is compiled if the development or deployment environment is running an older Node.js version. Vite 8 is also a meaningful part of the upgrade because the required release is the first Vite 8 version that bundles stable Rolldown, its newer bundler implementation. The SvelteKit documentation recommends upgrading to the latest 2.x release first so its deprecation warnings can expose problems before the major-version migration.
The first migration step should therefore happen before changing application code. Check the Node.js version used locally, in continuous integration, and by the production adapter, then confirm that the package versions in the project can satisfy SvelteKit 3's requirements. This matters particularly for teams that use different Node.js versions between development and deployment, because a local upgrade can appear successful while the production build still runs on an unsupported runtime. Once the environment is ready, the official migration command can make the next pass much less manual.
The migration command changes code, but it does not finish the upgrade
SvelteKit provides npx sv migrate sveltekit-3 --tasks all --confirm for existing projects. The command automatically applies migrations that can be performed safely and produces a TODO list for changes that still need developer attention. That distinction is important: the tool is a codemod, meaning it transforms known code patterns, rather than a test that can prove the application still behaves correctly. After it finishes, the generated changes should be reviewed instead of being treated as an upgrade verdict.
The safest workflow is to commit or otherwise preserve the working SvelteKit 2 state, run the migration, inspect the resulting diff, and then run the project's type checks, tests, development server, production build, and deployment process. The migration guide itself recommends moving to the latest SvelteKit 2 release first because targeted deprecation warnings can identify code that will need attention. This gives developers two useful signals instead of one: the automated migration tells them what can be changed mechanically, while the compiler and tests reveal what the application actually depends on.
SvelteKit 3 moves configuration from svelte.config.js into Vite
One of the most visible structural changes is that svelte.config.js is no longer supported as the place for SvelteKit configuration. The framework configuration now belongs in the SvelteKit Vite plugin inside vite.config.js or vite.config.ts, with former config.kit options becoming top-level plugin options. This puts SvelteKit configuration closer to the Vite configuration that already controls the build pipeline and allows Vite plugins to see those settings directly. Projects with custom Vite configuration or adapter-specific setup should pay particular attention to this move rather than assuming the migration tool can infer every local arrangement.
Several configuration names also change or disappear during the move. SvelteKit 3 removes preloadStrategy, replaces prerender.origin with paths.origin, and replaces csrf.checkOrigin with csrf.trustedOrigins. The last change is especially relevant to applications that previously disabled origin checking for forms: cross-site request forgery protection remains enabled, and trusted external origins must now be explicitly allowed instead of turning the check off. The new paths.origin setting is also important for deployments behind reverse proxies where the public origin cannot reliably be derived from request headers.
The familiar $lib alias becomes a standard package import
SvelteKit 3 no longer creates the $lib alias automatically. It replaces that convention with #lib, using Node.js subpath imports declared in the project's package.json. Existing imports such as $lib/server therefore need to be changed to the new import scheme, and the replacement can require explicit file extensions such as .js or .ts. This is more than a cosmetic rename because the new approach relies on a standard package mechanism that Vite and TypeScript can resolve natively.
The same cleanup appears in several framework modules. $app/environment becomes $app/env, while the old $service-worker module has been removed in favor of newer application and manifest APIs. Projects with service workers deserve a separate test pass because SvelteKit 3 also introduces a dedicated service-worker TypeScript configuration. The migration is therefore not simply a matter of replacing one string globally; the surrounding import and type configuration needs to remain coherent after the change.
Navigation APIs change in ways users can actually notice
SvelteKit 3 changes several navigation behaviors that can affect application state rather than just compilation. The old pushState and replaceState approach used for shallow routing is deprecated in favor of goto, while invalidateAll is deprecated in favor of refreshAll. Shallow routing now also triggers navigation hooks, and a link pointing to the current URL causes SvelteKit to refresh the page's data rather than simply doing nothing. Applications that depend on carefully controlled client-side state should test these paths because the changes can alter when data loads and when navigation hooks execute.
There is another behavioral change around goto: it now rejects when the target URL does not resolve to a route inside the application. External navigation should instead use the browser's normal location mechanism. This matters for code that uses a single navigation helper for both internal routes and external destinations, including authentication and payment flows. A migration can therefore pass type checking while an external redirect path still fails at runtime if it was relying on the old behavior.
Cookies and redirects get stricter for security reasons
SvelteKit 3 upgrades its cookie handling and changes a few defaults that can affect existing applications. Cookie names are now restricted to ASCII characters, and a cookie without an explicit path defaults to /, making it available across the site instead of requiring the developer to specify the path. The release also changes error handling around enhanced form actions so the status code returned by fail() is reflected instead of always becoming a successful-looking 200 response. These are easy changes to miss because the application may continue to build normally while authentication, form validation, or session behavior changes under specific requests.
External redirects now require an explicit opt-in. SvelteKit's migration documentation says developers can allow external destinations with the redirect options rather than treating every redirect target as trusted by default. This is particularly relevant to OAuth, payment gateways, and other integrations that deliberately send users away from the application after a server-side action. Before upgrading, search for redirect calls whose destination is outside the application's own routes and test those flows after the migration.
Server adapters have their own SvelteKit 3 migration work
The framework upgrade also reaches the deployment layer. The Node adapter now uses Rolldown through Vite 8, removes the old ORIGIN environment-variable approach in favor of paths.origin, and changes how static assets are recorded and served. The Vercel adapter no longer supports its previous edge runtime, while the Netlify adapter now follows the stable Netlify Frameworks API and has newer command-line requirements. Developers should therefore test the adapter as part of the application upgrade rather than stopping after a successful local development build.
Cloudflare deployments have their own API changes as well. The Cloudflare adapter moves values such as env and waitUntil away from SvelteKit's old platform object and toward Cloudflare's worker APIs, while the minimum Wrangler version is raised. That means a project using Cloudflare-specific code can require manual changes even when the general SvelteKit migration completes successfully. If the application is deployed through an adapter, the adapter's SvelteKit 3 compatibility should be tested before treating the framework upgrade as finished.
The safest SvelteKit 3 migration is a behavior test, not a package update
The useful checklist after the automated migration is surprisingly concrete: verify the Node.js and TypeScript versions, inspect the new Vite configuration, replace remaining legacy aliases and modules, test navigation and form behavior, check cookies and authentication, exercise external redirects, and run the production adapter locally before deployment. Applications using service workers, custom servers, OAuth, reverse proxies, or adapter-specific APIs deserve extra attention because those areas contain several of the release's behavioral changes. SvelteKit's migration tool can reduce repetitive editing, but it cannot know whether a redirect is business-critical or whether a cookie path is relied upon by an existing session system.
SvelteKit 3 is therefore a major version upgrade in the practical sense, even though the project remains recognizably the same framework. The release removes older conventions in favor of standard Vite, Node.js, and TypeScript mechanisms, while tightening several security and runtime behaviors. Developers starting new applications can use the new structure immediately; teams with established SvelteKit 2 projects should first bring the old project to its latest 2.x release, run the migration tool, review every generated change and TODO, and then test the application as a production system rather than merely checking whether the build turns green.
Written by


