diff --git a/docs/config.json b/docs/config.json
index e09f9d1de9..5a3dadd369 100644
--- a/docs/config.json
+++ b/docs/config.json
@@ -127,10 +127,6 @@
             {
               "label": "SSR & SvelteKit",
               "to": "framework/svelte/ssr"
-            },
-            {
-              "label": "Reactivity",
-              "to": "framework/svelte/reactivity"
             }
           ]
         },
diff --git a/docs/framework/svelte/devtools.md b/docs/framework/svelte/devtools.md
index db495f2c0e..c5dbfd4bef 100644
--- a/docs/framework/svelte/devtools.md
+++ b/docs/framework/svelte/devtools.md
@@ -55,7 +55,7 @@ Place the following code as high in your Svelte app as you can. The closer it is
 
 ### Options
 
-- `initialIsOpen: Boolean`
+- `initialIsOpen: boolean`
   - Set this `true` if you want the dev tools to default to being open
 - `buttonPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "relative"`
   - Defaults to `bottom-right`
diff --git a/docs/framework/svelte/installation.md b/docs/framework/svelte/installation.md
index e4ad607ee0..7fd45eb7df 100644
--- a/docs/framework/svelte/installation.md
+++ b/docs/framework/svelte/installation.md
@@ -5,8 +5,6 @@ title: Installation
 
 You can install Svelte Query via [NPM](https://npmjs.com).
 
-> v5 is currently available as a release-candidate. We don't anticipate any major API changes from here on out. We encourage you to try it out and report any issues you find.
-
 ### NPM
 
 ```bash
diff --git a/docs/framework/svelte/overview.md b/docs/framework/svelte/overview.md
index f1122355aa..e2cc39531e 100644
--- a/docs/framework/svelte/overview.md
+++ b/docs/framework/svelte/overview.md
@@ -28,19 +28,19 @@ Then call any function (e.g. createQuery) from any component:
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['todos'],
     queryFn: () => fetchTodos(),
-  })
+  }))
 </script>
 
 <div>
-  {#if $query.isLoading}
+  {#if query.isLoading}
     <p>Loading...</p>
-  {:else if $query.isError}
-    <p>Error: {$query.error.message}</p>
-  {:else if $query.isSuccess}
-    {#each $query.data as todo}
+  {:else if query.isError}
+    <p>Error: {query.error.message}</p>
+  {:else if query.isSuccess}
+    {#each query.data as todo}
       <p>{todo.title}</p>
     {/each}
   {/if}
@@ -62,6 +62,8 @@ Svelte Query offers useful functions and components that will make managing serv
 - `useQueryClient`
 - `useIsFetching`
 - `useIsMutating`
+- `useMutationState`
+- `useIsRestoring`
 - `useHydrate`
 - `<QueryClientProvider>`
 - `<HydrationBoundary>`
@@ -70,5 +72,4 @@ Svelte Query offers useful functions and components that will make managing serv
 
 Svelte Query offers an API similar to React Query, but there are some key differences to be mindful of.
 
-- Many of the functions in Svelte Query return a Svelte store. To access values on these stores reactively, you need to prefix the store with a `$`. You can learn more about Svelte stores [here](https://learn.svelte.dev/tutorial/writable-stores).
-- If your query or mutation depends on variables, you must use a store for the options. You can read more about this [here](../reactivity).
+- The arguments to the `create*` functions must be wrapped in a function to preserve reactivity.
diff --git a/docs/framework/svelte/reactivity.md b/docs/framework/svelte/reactivity.md
deleted file mode 100644
index 8fdab9d13a..0000000000
--- a/docs/framework/svelte/reactivity.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-id: reactivity
-title: Reactivity
----
-
-Svelte uses a compiler to build your code which optimizes rendering. By default, components run once, unless they are referenced in your markup. To be able to react to changes in options you need to use [stores](https://svelte.dev/docs/svelte-store).
-
-In the below example, the `refetchInterval` option is set from the variable `intervalMs`, which is bound to the input field. However, as the query is not able to react to changes in `intervalMs`, `refetchInterval` will not change when the input value changes.
-
-```svelte
-<script lang="ts">
-  import { createQuery } from '@tanstack/svelte-query'
-
-  const endpoint = 'http://localhost:5173/api/data'
-
-  let intervalMs = 1000
-
-  const query = createQuery({
-    queryKey: ['refetch'],
-    queryFn: async () => await fetch(endpoint).then((r) => r.json()),
-    refetchInterval: intervalMs,
-  })
-</script>
-
-<input type="number" bind:value={intervalMs} />
-```
-
-To solve this, we can convert `intervalMs` into a writable store. The query options can then be turned into a derived store, which will be passed into the function with true reactivity.
-
-```svelte
-<script lang="ts">
-  import { derived, writable } from 'svelte/store'
-  import { createQuery } from '@tanstack/svelte-query'
-
-  const endpoint = 'http://localhost:5173/api/data'
-
-  const intervalMs = writable(1000)
-
-  const query = createQuery(
-    derived(intervalMs, ($intervalMs) => ({
-      queryKey: ['refetch'],
-      queryFn: async () => await fetch(endpoint).then((r) => r.json()),
-      refetchInterval: $intervalMs,
-    })),
-  )
-</script>
-
-<input type="number" bind:value={$intervalMs} />
-```
diff --git a/docs/framework/svelte/ssr.md b/docs/framework/svelte/ssr.md
index ac6d5ee7ae..7448229caa 100644
--- a/docs/framework/svelte/ssr.md
+++ b/docs/framework/svelte/ssr.md
@@ -58,11 +58,11 @@ export async function load() {
 
   export let data: PageData
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['posts'],
     queryFn: getPosts,
     initialData: data.posts,
-  })
+  }))
 </script>
 ```
 
@@ -136,10 +136,10 @@ export async function load({ parent, fetch }) {
   import { createQuery } from '@tanstack/svelte-query'
 
   // This data is cached by prefetchQuery in +page.ts so no fetch actually happens here
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['posts'],
     queryFn: async () => (await fetch('/api/posts')).json(),
-  })
+  }))
 </script>
 ```
 
diff --git a/eslint.config.js b/eslint.config.js
index 3b5cd36f26..c5ffa2afd5 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -41,6 +41,7 @@ export default [
       '@typescript-eslint/no-unsafe-function-type': 'off',
       '@typescript-eslint/require-await': 'error',
       'no-case-declarations': 'off',
+      'prefer-const': 'off',
     },
   },
   {
diff --git a/examples/svelte/auto-refetching/src/routes/+layout.svelte b/examples/svelte/auto-refetching/src/routes/+layout.svelte
index ef60a2f559..4b170dc01e 100644
--- a/examples/svelte/auto-refetching/src/routes/+layout.svelte
+++ b/examples/svelte/auto-refetching/src/routes/+layout.svelte
@@ -4,6 +4,8 @@
   import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'
   import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
 
+  const { children } = $props()
+
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
@@ -15,7 +17,7 @@
 
 <QueryClientProvider client={queryClient}>
   <main>
-    <slot />
+    {@render children()}
   </main>
   <SvelteQueryDevtools />
 </QueryClientProvider>
diff --git a/examples/svelte/auto-refetching/src/routes/+page.svelte b/examples/svelte/auto-refetching/src/routes/+page.svelte
index ab5e83e17f..4a31304000 100644
--- a/examples/svelte/auto-refetching/src/routes/+page.svelte
+++ b/examples/svelte/auto-refetching/src/routes/+page.svelte
@@ -5,33 +5,35 @@
     createMutation,
   } from '@tanstack/svelte-query'
 
-  let intervalMs = 1000
-  let value = ''
+  let intervalMs = $state(1000)
+  let value = $state<string>('')
 
   const client = useQueryClient()
 
-  const endpoint = 'http://localhost:5173/api/data'
+  const endpoint = '/api/data'
 
-  $: todos = createQuery<{ items: string[] }>({
+  const todos = createQuery<{ items: string[] }>(() => ({
     queryKey: ['refetch'],
     queryFn: async () => await fetch(endpoint).then((r) => r.json()),
     // Refetch the data every second
     refetchInterval: intervalMs,
-  })
+  }))
 
-  const addMutation = createMutation({
+  const addMutation = createMutation(() => ({
     mutationFn: (value: string) =>
-      fetch(`${endpoint}?add=${value}`).then((r) => r.json()),
+      fetch(`${endpoint}?add=${encodeURIComponent(value)}`).then((r) =>
+        r.json(),
+      ),
     onSuccess: () => client.invalidateQueries({ queryKey: ['refetch'] }),
-  })
+  }))
 
-  const clearMutation = createMutation({
+  const clearMutation = createMutation(() => ({
     mutationFn: () => fetch(`${endpoint}?clear=1`).then((r) => r.json()),
     onSuccess: () => client.invalidateQueries({ queryKey: ['refetch'] }),
-  })
+  }))
 </script>
 
-<h1>Auto Refetch with stale-time set to 1s</h1>
+<h1>Auto Refetch with stale-time set to {(intervalMs / 1000).toFixed(2)}s</h1>
 
 <p>
   This example is best experienced on your own machine, where you can open
@@ -49,8 +51,8 @@
           margin-left:.5rem;
           width:.75rem;
           height:.75rem; 
-          background: {$todos.isFetching ? 'green' : 'transparent'};
-          transition: {!$todos.isFetching ? 'all .3s ease' : 'none'};
+          background: {todos.isFetching ? 'green' : 'transparent'};
+          transition: {!todos.isFetching ? 'all .3s ease' : 'none'};
           border-radius: 100%;
           transform: scale(1.5)"
     ></span>
@@ -58,10 +60,10 @@
 </label>
 <h2>Todo List</h2>
 <form
-  on:submit={(e) => {
+  onsubmit={(e) => {
     e.preventDefault()
     e.stopPropagation()
-    $addMutation.mutate(value, {
+    addMutation.mutate(value, {
       onSuccess: () => (value = ''),
     })
   }}
@@ -69,33 +71,39 @@
   <input placeholder="enter something" bind:value />
 </form>
 
-{#if $todos.isPending}
+{#if todos.isPending}
   Loading...
 {/if}
-{#if $todos.error}
+{#if todos.error}
   An error has occurred:
-  {$todos.error.message}
+  {todos.error.message}
 {/if}
-{#if $todos.isSuccess}
+{#if todos.isSuccess}
   <ul>
-    {#each $todos.data.items as item}
+    {#each todos.data.items as item}
       <li>{item}</li>
     {/each}
   </ul>
   <div>
-    <button on:click={() => $clearMutation.mutate(undefined)}>
-      Clear All
-    </button>
-  </div>
-{/if}
-{#if $todos.isFetching}
-  <div style="color:darkgreen; font-weight:700">
-    'Background Updating...' : ' '
+    <button onclick={() => clearMutation.mutate(undefined)}> Clear All </button>
   </div>
 {/if}
 
+<pre
+  class={['updating-text', todos.isFetching && 'on']}
+  style="font-weight:700">Background Updating...</pre>
+
 <style>
   li {
     text-align: left;
   }
+
+  .updating-text {
+    color: transparent;
+    transition: all 0.3s ease;
+  }
+  .updating-text.on {
+    color: green;
+    transition: none;
+  }
 </style>
diff --git a/examples/svelte/auto-refetching/svelte.config.js b/examples/svelte/auto-refetching/svelte.config.js
index 2dee2d78a1..d6b43b0085 100644
--- a/examples/svelte/auto-refetching/svelte.config.js
+++ b/examples/svelte/auto-refetching/svelte.config.js
@@ -3,13 +3,13 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-  // Consult https://github.com/sveltejs/svelte-preprocess
-  // for more information about preprocessors
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/examples/svelte/basic/src/lib/Post.svelte b/examples/svelte/basic/src/lib/Post.svelte
index 56472ce68f..49469c2fb5 100644
--- a/examples/svelte/basic/src/lib/Post.svelte
+++ b/examples/svelte/basic/src/lib/Post.svelte
@@ -3,29 +3,29 @@
   import { getPostById } from './data'
   import type { Post } from './types'
 
-  export let postId: number
+  const { postId }: { postId: number } = $props()
 
-  const post = createQuery<Post>({
+  const post = createQuery<Post>(() => ({
     queryKey: ['post', postId],
     queryFn: () => getPostById(postId),
-  })
+  }))
 </script>
 
 <div>
   <div>
     <a class="button" href="/"> Back </a>
   </div>
-  {#if !postId || $post.isPending}
+  {#if !postId || post.isPending}
     <span>Loading...</span>
   {/if}
-  {#if $post.error}
-    <span>Error: {$post.error.message}</span>
+  {#if post.error}
+    <span>Error: {post.error.message}</span>
   {/if}
-  {#if $post.isSuccess}
-    <h1>{$post.data.title}</h1>
+  {#if post.isSuccess}
+    <h1>{post.data.title}</h1>
     <div>
-      <p>{$post.data.body}</p>
+      <p>{post.data.body}</p>
     </div>
-    <div>{$post.isFetching ? 'Background Updating...' : ' '}</div>
+    <div>{post.isFetching ? 'Background Updating...' : ' '}</div>
   {/if}
 </div>
diff --git a/examples/svelte/basic/src/lib/Posts.svelte b/examples/svelte/basic/src/lib/Posts.svelte
index c4f2f2c642..1f19e7fe32 100644
--- a/examples/svelte/basic/src/lib/Posts.svelte
+++ b/examples/svelte/basic/src/lib/Posts.svelte
@@ -9,21 +9,21 @@
   const posts = createQuery<
     { id: number; title: string; body: string }[],
     Error
-  >({
+  >(() => ({
     queryKey: ['posts', limit],
     queryFn: () => getPosts(limit),
-  })
+  }))
 </script>
 
 <div>
   <div>
-    {#if $posts.status === 'pending'}
+    {#if posts.status === 'pending'}
       <span>Loading...</span>
-    {:else if $posts.status === 'error'}
-      <span>Error: {$posts.error.message}</span>
+    {:else if posts.status === 'error'}
+      <span>Error: {posts.error.message}</span>
     {:else}
       <ul>
-        {#each $posts.data as post}
+        {#each posts.data as post}
           <article>
             <a
               href={`/${post.id}`}
@@ -38,11 +38,9 @@
           </article>
         {/each}
       </ul>
-      {#if $posts.isFetching}
-        <div style="color:darkgreen; font-weight:700">
-          Background Updating...
-        </div>
-      {/if}
+      <pre
+        class={['updating-text', posts.isFetching && 'on']}
+        style="font-weight:700">Background Updating...</pre>
     {/if}
   </div>
 </div>
@@ -53,8 +51,16 @@
   }
   a {
     display: block;
-    color: white;
     font-size: 1.5rem;
     margin-bottom: 1rem;
   }
+
+  .updating-text {
+    color: transparent;
+    transition: all 0.3s ease;
+  }
+  .updating-text.on {
+    color: green;
+    transition: none;
+  }
 </style>
diff --git a/examples/svelte/basic/src/routes/+layout.svelte b/examples/svelte/basic/src/routes/+layout.svelte
index da5d841b0b..2cb76cd097 100644
--- a/examples/svelte/basic/src/routes/+layout.svelte
+++ b/examples/svelte/basic/src/routes/+layout.svelte
@@ -6,6 +6,8 @@
   import { PersistQueryClientProvider } from '@tanstack/svelte-query-persist-client'
   import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'
 
+  const { children } = $props()
+
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
@@ -21,7 +23,7 @@
 
 <PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>
   <main>
-    <slot />
+    {@render children()}
   </main>
   <SvelteQueryDevtools />
 </PersistQueryClientProvider>
diff --git a/examples/svelte/basic/src/routes/[postId]/+page.svelte b/examples/svelte/basic/src/routes/[postId]/+page.svelte
index b68acc0bc0..2400baac2a 100644
--- a/examples/svelte/basic/src/routes/[postId]/+page.svelte
+++ b/examples/svelte/basic/src/routes/[postId]/+page.svelte
@@ -1,8 +1,7 @@
 <script lang="ts">
   import Post from '$lib/Post.svelte'
-  import type { PageData } from './$types'
 
-  export let data: PageData
+  const { data } = $props()
 </script>
 
 <Post postId={data.postId} />
diff --git a/examples/svelte/basic/svelte.config.js b/examples/svelte/basic/svelte.config.js
index 2dee2d78a1..d6b43b0085 100644
--- a/examples/svelte/basic/svelte.config.js
+++ b/examples/svelte/basic/svelte.config.js
@@ -3,13 +3,13 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-  // Consult https://github.com/sveltejs/svelte-preprocess
-  // for more information about preprocessors
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/examples/svelte/load-more-infinite-scroll/src/app.css b/examples/svelte/load-more-infinite-scroll/src/app.css
index c57658b1ef..d301f1b2a3 100644
--- a/examples/svelte/load-more-infinite-scroll/src/app.css
+++ b/examples/svelte/load-more-infinite-scroll/src/app.css
@@ -48,7 +48,7 @@ main {
   text-align: center;
 }
 
-button {
+.button {
   border-radius: 8px;
   border: 1px solid transparent;
   padding: 0.6em 1.2em;
@@ -59,11 +59,11 @@ button {
   cursor: pointer;
   transition: border-color 0.25s;
 }
-button:hover {
+.button:hover {
   border-color: #646cff;
 }
-button:focus,
-button:focus-visible {
+.button:focus,
+.button:focus-visible {
   outline: 4px auto -webkit-focus-ring-color;
 }
 
@@ -75,7 +75,7 @@ button:focus-visible {
   a:hover {
     color: #747bff;
   }
-  button {
+  .button {
     background-color: #f9f9f9;
   }
 }
diff --git a/examples/svelte/load-more-infinite-scroll/src/lib/LoadMore.svelte b/examples/svelte/load-more-infinite-scroll/src/lib/LoadMore.svelte
index 79c602e672..c03a65441a 100644
--- a/examples/svelte/load-more-infinite-scroll/src/lib/LoadMore.svelte
+++ b/examples/svelte/load-more-infinite-scroll/src/lib/LoadMore.svelte
@@ -6,7 +6,7 @@
   const fetchPlanets = async ({ pageParam = 1 }) =>
     await fetch(`${endPoint}/planets/?page=${pageParam}`).then((r) => r.json())
 
-  const query = createInfiniteQuery({
+  const query = createInfiniteQuery(() => ({
     queryKey: ['planets'],
     queryFn: ({ pageParam }) => fetchPlanets({ pageParam }),
     initialPageParam: 1,
@@ -20,18 +20,18 @@
       }
       return undefined
     },
-  })
+  }))
 </script>
 
-{#if $query.isPending}
+{#if query.isPending}
   Loading...
 {/if}
-{#if $query.error}
-  <span>Error: {$query.error.message}</span>
+{#if query.error}
+  <span>Error: {query.error.message}</span>
 {/if}
-{#if $query.isSuccess}
+{#if query.isSuccess}
   <div>
-    {#each $query.data.pages as { results }}
+    {#each query.data.pages as { results }}
       {#each results as planet}
         <div class="card">
           <div class="card-body">
@@ -44,12 +44,12 @@
   </div>
   <div>
     <button
-      on:click={() => $query.fetchNextPage()}
-      disabled={!$query.hasNextPage || $query.isFetchingNextPage}
+      onclick={() => query.fetchNextPage()}
+      disabled={!query.hasNextPage || query.isFetchingNextPage}
     >
-      {#if $query.isFetching}
+      {#if query.isFetching}
         Loading more...
-      {:else if $query.hasNextPage}
+      {:else if query.hasNextPage}
         Load More
       {:else}Nothing more to load{/if}
     </button>
@@ -60,5 +60,6 @@
   .card {
     background-color: #111;
     margin-bottom: 1rem;
+    color: rgba(255, 255, 255, 0.87);
   }
 </style>
diff --git a/examples/svelte/load-more-infinite-scroll/src/routes/+layout.svelte b/examples/svelte/load-more-infinite-scroll/src/routes/+layout.svelte
index ef60a2f559..4b170dc01e 100644
--- a/examples/svelte/load-more-infinite-scroll/src/routes/+layout.svelte
+++ b/examples/svelte/load-more-infinite-scroll/src/routes/+layout.svelte
@@ -4,6 +4,8 @@
   import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'
   import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
 
+  const { children } = $props()
+
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
@@ -15,7 +17,7 @@
 
 <QueryClientProvider client={queryClient}>
   <main>
-    <slot />
+    {@render children()}
   </main>
   <SvelteQueryDevtools />
 </QueryClientProvider>
diff --git a/examples/svelte/load-more-infinite-scroll/svelte.config.js b/examples/svelte/load-more-infinite-scroll/svelte.config.js
index 0aa6cba937..d6b43b0085 100644
--- a/examples/svelte/load-more-infinite-scroll/svelte.config.js
+++ b/examples/svelte/load-more-infinite-scroll/svelte.config.js
@@ -3,13 +3,13 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-  // Consult https://kit.svelte.dev/docs/integrations#preprocessors
-  // for more information about preprocessors
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/examples/svelte/optimistic-updates/src/routes/+layout.svelte b/examples/svelte/optimistic-updates/src/routes/+layout.svelte
index ef60a2f559..4b170dc01e 100644
--- a/examples/svelte/optimistic-updates/src/routes/+layout.svelte
+++ b/examples/svelte/optimistic-updates/src/routes/+layout.svelte
@@ -4,6 +4,8 @@
   import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'
   import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
 
+  const { children } = $props()
+
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
@@ -15,7 +17,7 @@
 
 <QueryClientProvider client={queryClient}>
   <main>
-    <slot />
+    {@render children()}
   </main>
   <SvelteQueryDevtools />
 </QueryClientProvider>
diff --git a/examples/svelte/optimistic-updates/src/routes/+page.svelte b/examples/svelte/optimistic-updates/src/routes/+page.svelte
index af8738ffcc..0caf5ffe7b 100644
--- a/examples/svelte/optimistic-updates/src/routes/+page.svelte
+++ b/examples/svelte/optimistic-updates/src/routes/+page.svelte
@@ -16,11 +16,11 @@
     ts: number
   }
 
-  let text = ''
+  let text = $state<string>('')
 
   const client = useQueryClient()
 
-  const endpoint = 'http://localhost:5173/api/data'
+  const endpoint = '/api/data'
 
   const fetchTodos = async (): Promise<Todos> =>
     await fetch(endpoint).then((r) => r.json())
@@ -36,12 +36,12 @@
       }),
     }).then((res) => res.json())
 
-  const todos = createQuery<Todos>({
+  const todos = createQuery<Todos>(() => ({
     queryKey: ['optimistic'],
     queryFn: fetchTodos,
-  })
+  }))
 
-  const addTodoMutation = createMutation({
+  const addTodoMutation = createMutation(() => ({
     mutationFn: createTodo,
     onMutate: async (newTodo: string) => {
       text = ''
@@ -74,7 +74,7 @@
     onSettled: () => {
       client.invalidateQueries({ queryKey: ['optimistic'] })
     },
-  })
+  }))
 </script>
 
 <h1>Optimistic Updates</h1>
@@ -87,36 +87,36 @@
 </p>
 
 <form
-  on:submit={(e) => {
+  onsubmit={(e) => {
     e.preventDefault()
     e.stopPropagation()
-    $addTodoMutation.mutate(text)
+    addTodoMutation.mutate(text)
   }}
 >
   <div>
     <input type="text" bind:value={text} />
-    <button disabled={$addTodoMutation.isPending}>Create</button>
+    <button disabled={addTodoMutation.isPending}>Create</button>
   </div>
 </form>
 
-{#if $todos.isPending}
+{#if todos.isPending}
   Loading...
 {/if}
-{#if $todos.error}
+{#if todos.error}
   An error has occurred:
-  {$todos.error.message}
+  {todos.error.message}
 {/if}
-{#if $todos.isSuccess}
+{#if todos.isSuccess}
   <div class="mb-4">
-    Updated At: {new Date($todos.data.ts).toLocaleTimeString()}
+    Updated At: {new Date(todos.data.ts).toLocaleTimeString()}
   </div>
   <ul>
-    {#each $todos.data.items as todo}
+    {#each todos.data.items as todo}
       <li>{todo.text}</li>
     {/each}
   </ul>
 {/if}
-{#if $todos.isFetching}
+{#if todos.isFetching}
   <div style="color:darkgreen; font-weight:700">
     'Background Updating...' : ' '
   </div>
diff --git a/examples/svelte/optimistic-updates/src/routes/api/data/+server.ts b/examples/svelte/optimistic-updates/src/routes/api/data/+server.ts
index 46bfe05612..9cf65a54d2 100644
--- a/examples/svelte/optimistic-updates/src/routes/api/data/+server.ts
+++ b/examples/svelte/optimistic-updates/src/routes/api/data/+server.ts
@@ -6,7 +6,7 @@ type Todo = {
   text: string
 }
 
-const items: Todo[] = []
+const items: Array<Todo> = []
 
 /** @type {import('./$types').RequestHandler} */
 export const GET: RequestHandler = async (req) => {
diff --git a/examples/svelte/optimistic-updates/svelte.config.js b/examples/svelte/optimistic-updates/svelte.config.js
index 2dee2d78a1..d6b43b0085 100644
--- a/examples/svelte/optimistic-updates/svelte.config.js
+++ b/examples/svelte/optimistic-updates/svelte.config.js
@@ -3,13 +3,13 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-  // Consult https://github.com/sveltejs/svelte-preprocess
-  // for more information about preprocessors
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/examples/svelte/playground/src/lib/stores.svelte.ts b/examples/svelte/playground/src/lib/stores.svelte.ts
new file mode 100644
index 0000000000..18f0232ebb
--- /dev/null
+++ b/examples/svelte/playground/src/lib/stores.svelte.ts
@@ -0,0 +1,37 @@
+export function ref<T>(initial: T) {
+  let value = $state(initial)
+
+  return {
+    get value() {
+      return value
+    },
+    set value(newValue) {
+      value = newValue
+    },
+  }
+}
+
+export const staleTime = ref(1000)
+export const gcTime = ref(3000)
+export const errorRate = ref(0.05)
+export const queryTimeMin = ref(1000)
+export const queryTimeMax = ref(2000)
+
+export const editingIndex = ref<number | null>(null)
+export const views = ref(['', 'fruit', 'grape'])
+
+let initialId = 0
+const initialList = [
+  'apple',
+  'banana',
+  'pineapple',
+  'grapefruit',
+  'dragonfruit',
+  'grapes',
+].map((d) => ({ id: initialId++, name: d, notes: 'These are some notes' }))
+
+export const list = ref(initialList)
+export const id = ref(initialId)
+
+export type Todos = typeof initialList
+export type Todo = Todos[0]
diff --git a/examples/svelte/playground/src/lib/stores.ts b/examples/svelte/playground/src/lib/stores.ts
deleted file mode 100644
index 2dcdd669a6..0000000000
--- a/examples/svelte/playground/src/lib/stores.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { writable } from 'svelte/store'
-
-export const staleTime = writable(1000)
-export const gcTime = writable(3000)
-export const errorRate = writable(0.05)
-export const queryTimeMin = writable(1000)
-export const queryTimeMax = writable(2000)
-
-export const editingIndex = writable<number | null>(null)
-export const views = writable(['', 'fruit', 'grape'])
-
-let initialId = 0
-const initialList = [
-  'apple',
-  'banana',
-  'pineapple',
-  'grapefruit',
-  'dragonfruit',
-  'grapes',
-].map((d) => ({ id: initialId++, name: d, notes: 'These are some notes' }))
-
-export const list = writable(initialList)
-export const id = writable(initialId)
-
-export type Todos = typeof initialList
-export type Todo = Todos[0]
diff --git a/examples/svelte/playground/src/routes/+layout.svelte b/examples/svelte/playground/src/routes/+layout.svelte
index 1b9267032c..76c2d0d277 100644
--- a/examples/svelte/playground/src/routes/+layout.svelte
+++ b/examples/svelte/playground/src/routes/+layout.svelte
@@ -4,6 +4,8 @@
   import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'
   import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
 
+  const { children } = $props()
+
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
@@ -19,7 +21,7 @@
 
 <QueryClientProvider client={queryClient}>
   <div id="app">
-    <slot />
+    {@render children()}
   </div>
   <SvelteQueryDevtools />
 </QueryClientProvider>
diff --git a/examples/svelte/playground/src/routes/+page.svelte b/examples/svelte/playground/src/routes/+page.svelte
index 4830d01eb3..cec4a24208 100644
--- a/examples/svelte/playground/src/routes/+page.svelte
+++ b/examples/svelte/playground/src/routes/+page.svelte
@@ -6,15 +6,15 @@
     errorRate,
     queryTimeMin,
     queryTimeMax,
-  } from '../lib/stores'
+  } from '../lib/stores.svelte'
   import App from './App.svelte'
 
   const queryClient = useQueryClient()
 
   queryClient.setDefaultOptions({
     queries: {
-      staleTime: $staleTime,
-      gcTime: $gcTime,
+      staleTime: staleTime.value,
+      gcTime: gcTime.value,
     },
   })
 </script>
@@ -29,7 +29,7 @@
     type="number"
     min="0"
     step="1000"
-    bind:value={$staleTime}
+    bind:value={staleTime.value}
     style="width: 100px"
   />
 </div>
@@ -39,7 +39,7 @@
     type="number"
     min="0"
     step="1000"
-    bind:value={$gcTime}
+    bind:value={gcTime.value}
     style="width: 100px"
   />
 </div>
@@ -51,7 +51,7 @@
     min="0"
     max="1"
     step=".05"
-    bind:value={$errorRate}
+    bind:value={errorRate.value}
     style="width: 100px"
   />
 </div>
@@ -61,7 +61,7 @@
     type="number"
     min="1"
     step="500"
-    bind:value={$queryTimeMin}
+    bind:value={queryTimeMin.value}
     style="width: 100px"
   />{' '}
 </div>
@@ -71,7 +71,7 @@
     type="number"
     min="1"
     step="500"
-    bind:value={$queryTimeMax}
+    bind:value={queryTimeMax.value}
     style="width: 100px"
   />
 </div>
diff --git a/examples/svelte/playground/src/routes/AddTodo.svelte b/examples/svelte/playground/src/routes/AddTodo.svelte
index 5fe8fc4dcd..f482f6c2f1 100644
--- a/examples/svelte/playground/src/routes/AddTodo.svelte
+++ b/examples/svelte/playground/src/routes/AddTodo.svelte
@@ -1,55 +1,67 @@
 <script lang="ts">
   import { createMutation, useQueryClient } from '@tanstack/svelte-query'
-  import { errorRate, queryTimeMin, queryTimeMax, list, id } from '$lib/stores'
-  import type { Todo } from '$lib/stores'
+  import {
+    errorRate,
+    queryTimeMin,
+    queryTimeMax,
+    list,
+    id,
+  } from '$lib/stores.svelte'
+  import type { Todo } from '$lib/stores.svelte'
 
   const queryClient = useQueryClient()
 
-  let name = ''
+  let name = $state('')
 
   const postTodo = async ({ name, notes }: Omit<Todo, 'id'>) => {
-    console.info('postTodo', { name, notes })
     return new Promise((resolve, reject) => {
       setTimeout(
         () => {
-          if (Math.random() < $errorRate) {
+          if (Math.random() < errorRate.value) {
             return reject(
-              new Error(JSON.stringify({ postTodo: { name, notes } }, null, 2)),
+              new Error(
+                JSON.stringify(
+                  { postTodo: { name: $state.snapshot(name), notes } },
+                  null,
+                  2,
+                ),
+              ),
             )
           }
-          const todo = { name, notes, id: $id }
-          id.set($id + 1)
-          list.set([...$list, todo])
+          const todo = { name, notes, id: id.value }
+          id.value = id.value + 1
+          list.value.push(todo)
           resolve(todo)
         },
-        $queryTimeMin + Math.random() * ($queryTimeMax - $queryTimeMin),
+        queryTimeMin.value +
+          Math.random() * (queryTimeMax.value - queryTimeMin.value),
       )
     })
   }
 
-  const addMutation = createMutation({
+  const addMutation = createMutation(() => ({
     mutationFn: postTodo,
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: ['todos'] })
     },
-  })
+  }))
 </script>
 
 <div>
-  <input bind:value={name} disabled={$addMutation.status === 'pending'} />
+  <input bind:value={name} disabled={addMutation.status === 'pending'} />
 
   <button
-    on:click={() => $addMutation.mutate({ name, notes: name })}
-    disabled={$addMutation.status === 'pending' || !name}
+    onclick={() => addMutation.mutate({ name, notes: name })}
+    disabled={addMutation.status === 'pending' || !name}
   >
     Add Todo
   </button>
 
   <div>
-    {$addMutation.status === 'pending'
+    {addMutation.status === 'pending'
       ? 'Saving...'
-      : $addMutation.status === 'error'
-        ? $addMutation.error.message
+      : addMutation.status === 'error'
+        ? addMutation.error.message
         : 'Saved!'}
   </div>
 </div>
diff --git a/examples/svelte/playground/src/routes/App.svelte b/examples/svelte/playground/src/routes/App.svelte
index 5a72f454c0..bd909aae90 100644
--- a/examples/svelte/playground/src/routes/App.svelte
+++ b/examples/svelte/playground/src/routes/App.svelte
@@ -3,21 +3,21 @@
   import TodosList from './TodosList.svelte'
   import EditTodo from './EditTodo.svelte'
   import AddTodo from './AddTodo.svelte'
-  import { views, editingIndex } from '../lib/stores'
+  import { views, editingIndex } from '../lib/stores.svelte'
 
   const queryClient = useQueryClient()
 </script>
 
 <div>
   <div>
-    <button on:click={() => queryClient.invalidateQueries()}>
+    <button onclick={() => queryClient.invalidateQueries()}>
       Force Refetch All
     </button>
   </div>
   <br />
   <hr />
 
-  {#each $views as view}
+  {#each views.value as view}
     <div>
       <TodosList initialFilter={view} />
       <br />
@@ -25,15 +25,15 @@
   {/each}
 
   <button
-    on:click={() => {
-      views.set([...$views, ''])
+    onclick={() => {
+      views.value.push('')
     }}
   >
     Add Filter List
   </button>
   <hr />
 
-  {#if $editingIndex !== null}
+  {#if editingIndex.value !== null}
     <EditTodo />
     <hr />
   {/if}
diff --git a/examples/svelte/playground/src/routes/EditTodo.svelte b/examples/svelte/playground/src/routes/EditTodo.svelte
index 40b2208e60..d38c232221 100644
--- a/examples/svelte/playground/src/routes/EditTodo.svelte
+++ b/examples/svelte/playground/src/routes/EditTodo.svelte
@@ -10,23 +10,21 @@
     queryTimeMax,
     list,
     editingIndex,
-  } from '$lib/stores'
-  import { derived } from 'svelte/store'
-  import type { Todo } from '$lib/stores'
+  } from '$lib/stores.svelte'
+  import type { Todo } from '$lib/stores.svelte'
 
   const queryClient = useQueryClient()
 
   const fetchTodoById = async ({ id }: { id: number }): Promise<Todo> => {
-    console.info('fetchTodoById', { id })
     return new Promise((resolve, reject) => {
       setTimeout(
         () => {
-          if (Math.random() < $errorRate) {
+          if (Math.random() < errorRate.value) {
             return reject(
               new Error(JSON.stringify({ fetchTodoById: { id } }, null, 2)),
             )
           }
-          const todo = $list.find((d) => d.id === id)
+          const todo = $state.snapshot(list.value.find((d) => d.id === id))
           if (!todo) {
             return reject(
               new Error(JSON.stringify({ fetchTodoById: { id } }, null, 2)),
@@ -34,7 +32,8 @@
           }
           resolve(todo)
         },
-        $queryTimeMin + Math.random() * ($queryTimeMax - $queryTimeMin),
+        queryTimeMin.value +
+          Math.random() * (queryTimeMax.value - queryTimeMin.value),
       )
     })
   }
@@ -44,7 +43,7 @@
     return new Promise((resolve, reject) => {
       setTimeout(
         () => {
-          if (Math.random() < $errorRate) {
+          if (Math.random() < errorRate.value) {
             return reject(
               new Error(JSON.stringify({ patchTodo: todo }, null, 2)),
             )
@@ -54,60 +53,58 @@
               new Error(JSON.stringify({ patchTodo: todo }, null, 2)),
             )
           }
-          list.set(
-            $list.map((d) => {
-              if (d.id === todo.id) {
-                return todo
-              }
-              return d
-            }),
-          )
+          list.value = list.value.map((d) => {
+            if (d.id === todo.id) {
+              return $state.snapshot(todo)
+            }
+            return d
+          })
           resolve(todo)
         },
-        $queryTimeMin + Math.random() * ($queryTimeMax - $queryTimeMin),
+        queryTimeMin.value +
+          Math.random() * (queryTimeMax.value - queryTimeMin.value),
       )
     })
   }
 
-  const query = createQuery(
-    derived(editingIndex, ($editingIndex) => ({
-      queryKey: ['todo', { id: $editingIndex }],
-      queryFn: () => fetchTodoById({ id: $editingIndex || 0 }),
-      enabled: $editingIndex !== null,
-    })),
-  )
+  const query = createQuery(() => ({
+    queryKey: ['todo', { id: editingIndex.value }],
+    queryFn: () => fetchTodoById({ id: editingIndex.value || 0 }),
+    enabled: editingIndex.value !== null,
+  }))
 
-  const saveMutation = createMutation({
+  const saveMutation = createMutation(() => ({
     mutationFn: patchTodo,
     onSuccess: (data) => {
       // Update `todos` and the individual todo queries when this mutation succeeds
       queryClient.invalidateQueries({ queryKey: ['todos'] })
       queryClient.setQueryData(['todo', { id: editingIndex }], data)
     },
-  })
+  }))
 
-  $: todo = $query.data
+  const todo = $derived(query.data)
 
   const onSave = () => {
-    $saveMutation.mutate(todo)
+    saveMutation.mutate(todo)
   }
 
-  $: disableEditSave =
-    $query.status === 'pending' || $saveMutation.status === 'pending'
+  const disableEditSave = $derived(
+    query.status === 'pending' || saveMutation.status === 'pending',
+  )
 </script>
 
 <div>
   <div>
-    {#if $query.data}
-      <button on:click={() => editingIndex.set(null)}>Back</button> Editing Todo
-      "{$query.data.name}" (#{$editingIndex})
+    {#if query.data}
+      <button onclick={() => (editingIndex.value = null)}>Back</button> Editing
+      Todo "{query.data.name}" (#{editingIndex.value})
     {/if}
   </div>
-  {#if $query.status === 'pending'}
-    <span>Loading... (Attempt: {$query.failureCount + 1})</span>
-  {:else if $query.error}
+  {#if query.status === 'pending'}
+    <span>Loading... (Attempt: {query.failureCount + 1})</span>
+  {:else if query.error}
     <span>
-      Error! <button on:click={() => $query.refetch()}>Retry</button>
+      Error! <button onclick={() => query.refetch()}>Retry</button>
     </span>
   {:else if todo}
     <label>
@@ -119,19 +116,19 @@
       <input bind:value={todo.notes} disabled={disableEditSave} />
     </label>
     <div>
-      <button on:click={onSave} disabled={disableEditSave}> Save </button>
+      <button onclick={onSave} disabled={disableEditSave}> Save </button>
     </div>
     <div>
-      {$saveMutation.status === 'pending'
+      {saveMutation.status === 'pending'
         ? 'Saving...'
-        : $saveMutation.status === 'error'
-          ? $saveMutation.error.message
+        : saveMutation.status === 'error'
+          ? saveMutation.error.message
           : 'Saved!'}
     </div>
     <div>
-      {#if $query.isFetching}
+      {#if query.isFetching}
         <span>
-          Background Refreshing... (Attempt: {$query.failureCount + 1})
+          Background Refreshing... (Attempt: {query.failureCount + 1})
         </span>
       {:else}
         <span>&nbsp;</span>
diff --git a/examples/svelte/playground/src/routes/TodosList.svelte b/examples/svelte/playground/src/routes/TodosList.svelte
index 586af38e35..a7d6f392cc 100644
--- a/examples/svelte/playground/src/routes/TodosList.svelte
+++ b/examples/svelte/playground/src/routes/TodosList.svelte
@@ -6,68 +6,66 @@
     queryTimeMax,
     list,
     editingIndex,
-  } from '$lib/stores'
-  import { derived, writable } from 'svelte/store'
-  import type { Todos } from '$lib/stores'
+  } from '$lib/stores.svelte'
+  import type { Todos } from '$lib/stores.svelte'
 
-  export let initialFilter: string
+  let { initialFilter }: { initialFilter: string } = $props()
 
-  let filter = writable(initialFilter)
+  let filter = $state(initialFilter)
 
   const fetchTodos = async ({ filter }: { filter: string }): Promise<Todos> => {
     return new Promise((resolve, reject) => {
       setTimeout(
         () => {
-          if (Math.random() < $errorRate) {
+          if (Math.random() < errorRate.value) {
             return reject(
               new Error(JSON.stringify({ fetchTodos: { filter } }, null, 2)),
             )
           }
-          resolve($list.filter((d) => d.name.includes(filter)))
+          resolve(list.value.filter((d) => d.name.includes(filter)))
         },
-        $queryTimeMin + Math.random() * ($queryTimeMax - $queryTimeMin),
+        queryTimeMin.value +
+          Math.random() * (queryTimeMax.value - queryTimeMin.value),
       )
     })
   }
 
-  const query = createQuery(
-    derived(filter, ($filter) => ({
-      queryKey: ['todos', { filter: $filter }],
-      queryFn: () => fetchTodos({ filter: $filter }),
-    })),
-  )
+  const query = createQuery(() => ({
+    queryKey: ['todos', { filter: filter }],
+    queryFn: () => fetchTodos({ filter: filter }),
+  }))
 </script>
 
 <div>
   <label>
     Filter:{' '}
-    <input bind:value={$filter} />
+    <input bind:value={filter} />
   </label>
 </div>
 
-{#if $query.status === 'pending'}
-  <span>Loading... (Attempt: {$query.failureCount + 1})</span>
-{:else if $query.status === 'error'}
+{#if query.status === 'pending'}
+  <span>Loading... (Attempt: {query.failureCount + 1})</span>
+{:else if query.status === 'error'}
   <span>
-    Error: {$query.error.message}
+    Error: {query.error.message}
     <br />
-    <button on:click={() => $query.refetch()}>Retry</button>
+    <button onclick={() => query.refetch()}>Retry</button>
   </span>
 {:else}
   <ul>
-    {#if $query.data}
-      {#each $query.data as todo}
+    {#if query.data}
+      {#each query.data as todo}
         <li>
           {todo.name}{' '}
-          <button on:click={() => editingIndex.set(todo.id)}> Edit </button>
+          <button onclick={() => (editingIndex.value = todo.id)}> Edit </button>
         </li>
       {/each}
     {/if}
   </ul>
   <div>
-    {#if $query.isFetching}
+    {#if query.isFetching}
       <span>
-        Background Refreshing... (Attempt: {$query.failureCount + 1})
+        Background Refreshing... (Attempt: {query.failureCount + 1})
       </span>
     {:else}
       <span>&nbsp;</span>
diff --git a/examples/svelte/playground/svelte.config.js b/examples/svelte/playground/svelte.config.js
index a52aed3a7b..d6b43b0085 100644
--- a/examples/svelte/playground/svelte.config.js
+++ b/examples/svelte/playground/svelte.config.js
@@ -4,10 +4,12 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/examples/svelte/simple/src/lib/Simple.svelte b/examples/svelte/simple/src/lib/Simple.svelte
index 6b044dc321..a467e91393 100644
--- a/examples/svelte/simple/src/lib/Simple.svelte
+++ b/examples/svelte/simple/src/lib/Simple.svelte
@@ -9,32 +9,32 @@
     forks_count: number
   }
 
-  const query = createQuery<Repo>({
+  const query = createQuery<Repo>(() => ({
     queryKey: ['repoData'],
     queryFn: async () =>
       await fetch('https://api.github.com/repos/TanStack/query').then((r) =>
         r.json(),
       ),
-  })
+  }))
 </script>
 
 <h1>Simple</h1>
 <div class="my-4">
   <div>
-    {#if $query.isPending}
+    {#if query.isPending}
       Loading...
     {/if}
-    {#if $query.error}
+    {#if query.error}
       An error has occurred:
-      {$query.error.message}
+      {query.error.message}
     {/if}
-    {#if $query.isSuccess}
+    {#if query.isSuccess}
       <div>
-        <h1>{$query.data.full_name}</h1>
-        <p>{$query.data.description}</p>
-        <strong>👀 {$query.data.subscribers_count}</strong>{' '}
-        <strong>✨ {$query.data.stargazers_count}</strong>{' '}
-        <strong>🍴 {$query.data.forks_count}</strong>
+        <h1>{query.data.full_name}</h1>
+        <p>{query.data.description}</p>
+        <strong>👀 {query.data.subscribers_count}</strong>{' '}
+        <strong>✨ {query.data.stargazers_count}</strong>{' '}
+        <strong>🍴 {query.data.forks_count}</strong>
       </div>
     {/if}
   </div>
diff --git a/examples/svelte/simple/src/main.ts b/examples/svelte/simple/src/main.ts
index 7ad46094a0..eeb0a0bcec 100644
--- a/examples/svelte/simple/src/main.ts
+++ b/examples/svelte/simple/src/main.ts
@@ -1,7 +1,8 @@
+import { mount } from 'svelte'
 import './app.css'
 import App from './App.svelte'
 
-const app = new App({
+const app = mount(App, {
   target: document.querySelector('#app')!,
 })
 
diff --git a/examples/svelte/simple/svelte.config.js b/examples/svelte/simple/svelte.config.js
index ec6a224d76..64c513012f 100644
--- a/examples/svelte/simple/svelte.config.js
+++ b/examples/svelte/simple/svelte.config.js
@@ -1,7 +1,8 @@
 import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 
 export default {
-  // Consult https://github.com/sveltejs/svelte-preprocess
-  // for more information about preprocessors
   preprocess: vitePreprocess(),
+  compilerOptions: {
+    runes: true,
+  },
 }
diff --git a/examples/svelte/ssr/src/lib/Post.svelte b/examples/svelte/ssr/src/lib/Post.svelte
index 0de658b6dd..10b4df1949 100644
--- a/examples/svelte/ssr/src/lib/Post.svelte
+++ b/examples/svelte/ssr/src/lib/Post.svelte
@@ -3,29 +3,29 @@
   import { api } from './api'
   import type { Post } from './types'
 
-  export let postId: number
+  const { postId }: { postId: number } = $props()
 
-  const post = createQuery<Post>({
+  const post = createQuery<Post>(() => ({
     queryKey: ['post', postId],
     queryFn: () => api().getPostById(postId),
-  })
+  }))
 </script>
 
 <div>
   <div>
     <a class="button" href="/"> Back </a>
   </div>
-  {#if !postId || $post.isPending}
+  {#if !postId || post.isPending}
     <span>Loading...</span>
   {/if}
-  {#if $post.error}
-    <span>Error: {$post.error.message}</span>
+  {#if post.error}
+    <span>Error: {post.error.message}</span>
   {/if}
-  {#if $post.isSuccess}
-    <h1>{$post.data.title}</h1>
+  {#if post.isSuccess}
+    <h1>{post.data.title}</h1>
     <div>
-      <p>{$post.data.body}</p>
+      <p>{post.data.body}</p>
     </div>
-    <div>{$post.isFetching ? 'Background Updating...' : ' '}</div>
+    <div>{post.isFetching ? 'Background Updating...' : ' '}</div>
   {/if}
 </div>
diff --git a/examples/svelte/ssr/src/lib/Posts.svelte b/examples/svelte/ssr/src/lib/Posts.svelte
index 7457dfd49b..5de76de86a 100644
--- a/examples/svelte/ssr/src/lib/Posts.svelte
+++ b/examples/svelte/ssr/src/lib/Posts.svelte
@@ -4,26 +4,26 @@
 
   const client = useQueryClient()
 
-  let limit = 10
+  const limit = 10
 
   const posts = createQuery<
     { id: number; title: string; body: string }[],
     Error
-  >({
+  >(() => ({
     queryKey: ['posts', limit],
     queryFn: () => api().getPosts(limit),
-  })
+  }))
 </script>
 
 <div>
   <div>
-    {#if $posts.status === 'pending'}
+    {#if posts.status === 'pending'}
       <span>Loading...</span>
-    {:else if $posts.status === 'error'}
-      <span>Error: {$posts.error.message}</span>
+    {:else if posts.status === 'error'}
+      <span>Error: {posts.error.message}</span>
     {:else}
       <ul>
-        {#each $posts.data as post}
+        {#each posts.data as post}
           <article>
             <a
               href={`/${post.id}`}
@@ -38,11 +38,9 @@
           </article>
         {/each}
       </ul>
-      {#if $posts.isFetching}
-        <div style="color:darkgreen; font-weight:700">
-          Background Updating...
-        </div>
-      {/if}
+      <pre
+        class={['updating-text', posts.isFetching && 'on']}
+        style="font-weight:700">Background Updating...</pre>
     {/if}
   </div>
 </div>
@@ -53,8 +51,15 @@
   }
   a {
     display: block;
-    color: white;
     font-size: 1.5rem;
     margin-bottom: 1rem;
   }
+  .updating-text {
+    color: transparent;
+    transition: all 0.3s ease;
+  }
+  .updating-text.on {
+    color: green;
+    transition: none;
+  }
 </style>
diff --git a/examples/svelte/ssr/src/routes/+layout.svelte b/examples/svelte/ssr/src/routes/+layout.svelte
index d639174e3f..0b02447853 100644
--- a/examples/svelte/ssr/src/routes/+layout.svelte
+++ b/examples/svelte/ssr/src/routes/+layout.svelte
@@ -2,14 +2,13 @@
   import '../app.css'
   import { QueryClientProvider } from '@tanstack/svelte-query'
   import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
-  import type { PageData } from './$types'
 
-  export let data: PageData
+  const { data, children } = $props()
 </script>
 
 <QueryClientProvider client={data.queryClient}>
   <main>
-    <slot />
+    {@render children()}
   </main>
   <SvelteQueryDevtools />
 </QueryClientProvider>
diff --git a/examples/svelte/ssr/src/routes/+layout.ts b/examples/svelte/ssr/src/routes/+layout.ts
index 0d38c02919..f922afcc92 100644
--- a/examples/svelte/ssr/src/routes/+layout.ts
+++ b/examples/svelte/ssr/src/routes/+layout.ts
@@ -1,8 +1,8 @@
-import { browser } from '$app/environment'
 import { QueryClient } from '@tanstack/svelte-query'
 import type { LayoutLoad } from './$types'
+import { browser } from '$app/environment'
 
-export const load: LayoutLoad = async () => {
+export const load: LayoutLoad = () => {
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
diff --git a/examples/svelte/ssr/src/routes/+page.ts b/examples/svelte/ssr/src/routes/+page.ts
index 22d8f8ffbe..811b0d3a14 100644
--- a/examples/svelte/ssr/src/routes/+page.ts
+++ b/examples/svelte/ssr/src/routes/+page.ts
@@ -1,5 +1,5 @@
-import { api } from '$lib/api'
 import type { PageLoad } from './$types'
+import { api } from '$lib/api'
 
 export const load: PageLoad = async ({ parent, fetch }) => {
   const { queryClient } = await parent()
diff --git a/examples/svelte/ssr/src/routes/[postId]/+page.svelte b/examples/svelte/ssr/src/routes/[postId]/+page.svelte
index b68acc0bc0..2400baac2a 100644
--- a/examples/svelte/ssr/src/routes/[postId]/+page.svelte
+++ b/examples/svelte/ssr/src/routes/[postId]/+page.svelte
@@ -1,8 +1,7 @@
 <script lang="ts">
   import Post from '$lib/Post.svelte'
-  import type { PageData } from './$types'
 
-  export let data: PageData
+  const { data } = $props()
 </script>
 
 <Post postId={data.postId} />
diff --git a/examples/svelte/ssr/src/routes/[postId]/+page.ts b/examples/svelte/ssr/src/routes/[postId]/+page.ts
index b9cca0729b..87c9fa8a43 100644
--- a/examples/svelte/ssr/src/routes/[postId]/+page.ts
+++ b/examples/svelte/ssr/src/routes/[postId]/+page.ts
@@ -1,5 +1,5 @@
-import { api } from '$lib/api'
 import type { PageLoad } from './$types'
+import { api } from '$lib/api'
 
 export const load: PageLoad = async ({ parent, fetch, params }) => {
   const { queryClient } = await parent()
diff --git a/examples/svelte/ssr/svelte.config.js b/examples/svelte/ssr/svelte.config.js
index 2dee2d78a1..d6b43b0085 100644
--- a/examples/svelte/ssr/svelte.config.js
+++ b/examples/svelte/ssr/svelte.config.js
@@ -3,13 +3,13 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-  // Consult https://github.com/sveltejs/svelte-preprocess
-  // for more information about preprocessors
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/examples/svelte/star-wars/src/routes/+layout.svelte b/examples/svelte/star-wars/src/routes/+layout.svelte
index d11124d6fe..5f2bf488e9 100644
--- a/examples/svelte/star-wars/src/routes/+layout.svelte
+++ b/examples/svelte/star-wars/src/routes/+layout.svelte
@@ -4,6 +4,8 @@
   import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'
   import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
 
+  const { children } = $props()
+
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: {
@@ -25,6 +27,6 @@
     <a href="/films">Films</a>
     <a href="/characters">Characters</a>
   </nav>
-  <slot />
+  {@render children()}
   <SvelteQueryDevtools />
 </QueryClientProvider>
diff --git a/examples/svelte/star-wars/src/routes/+page.svelte b/examples/svelte/star-wars/src/routes/+page.svelte
index eaaf33aa03..939c72ec97 100644
--- a/examples/svelte/star-wars/src/routes/+page.svelte
+++ b/examples/svelte/star-wars/src/routes/+page.svelte
@@ -2,8 +2,7 @@
   <h2 class="text-4xl">React Query Demo</h2>
   <p>Using the Star Wars API</p>
   <p>
-    (Built by <a href="https://twitter.com/Brent_m_Clark">@Brent_m_Clark</a>
-    )
+    (Built by <a href="https://twitter.com/Brent_m_Clark">@Brent_m_Clark</a>)
   </p>
   <section>
     <h5 class="text-2xl">Why React Query?</h5>
diff --git a/examples/svelte/star-wars/src/routes/characters/+page.svelte b/examples/svelte/star-wars/src/routes/characters/+page.svelte
index 0fef65bd7a..7c59efd108 100644
--- a/examples/svelte/star-wars/src/routes/characters/+page.svelte
+++ b/examples/svelte/star-wars/src/routes/characters/+page.svelte
@@ -6,24 +6,24 @@
     return await res.json()
   }
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['characters'],
     queryFn: getCharacters,
-  })
+  }))
 </script>
 
-{#if $query.status === 'pending'}
+{#if query.status === 'pending'}
   <p>Loading...</p>
 {/if}
 
-{#if $query.status === 'error'}
+{#if query.status === 'error'}
   <p>Error :(</p>
 {/if}
 
-{#if $query.status === 'success'}
+{#if query.status === 'success'}
   <div>
     <h2 class="text-4xl">Characters</h2>
-    {#each $query.data.results as person}
+    {#each query.data.results as person}
       {@const personUrlParts = person.url.split('/').filter(Boolean)}
       {@const personId = personUrlParts[personUrlParts.length - 1]}
       <article>
diff --git a/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.svelte b/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.svelte
index 6743ccbcb5..03b77de532 100644
--- a/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.svelte
+++ b/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.svelte
@@ -2,36 +2,34 @@
   import { createQuery } from '@tanstack/svelte-query'
   import Homeworld from './Homeworld.svelte'
   import Film from './Film.svelte'
-  import type { PageData } from './$types'
-
-  export let data: PageData
+  import { page } from '$app/state'
 
   const getCharacter = async () => {
     const res = await fetch(
-      `https://swapi.dev/api/people/${data.params.characterId}/`,
+      `https://swapi.dev/api/people/${page.params.characterId}/`,
     )
     return await res.json()
   }
 
-  const query = createQuery({
-    queryKey: ['character', data.params.characterId],
+  const query = createQuery(() => ({
+    queryKey: ['character', page.params.characterId],
     queryFn: getCharacter,
-  })
+  }))
 </script>
 
-{#if $query.status === 'pending'}
+{#if query.status === 'pending'}
   <p>Loading...</p>
 {/if}
 
-{#if $query.status === 'error'}
+{#if query.status === 'error'}
   <p>Error :(</p>
 {/if}
 
-{#if $query.status === 'success'}
-  {@const homeworldUrlParts = $query.data.homeworld.split('/').filter(Boolean)}
+{#if query.status === 'success'}
+  {@const homeworldUrlParts = query.data.homeworld.split('/').filter(Boolean)}
   {@const homeworldId = homeworldUrlParts[homeworldUrlParts.length - 1]}
   <div>
-    <h2 class="text-4xl">{$query.data.name}</h2>
+    <h2 class="text-4xl">{query.data.name}</h2>
     <table>
       <thead>
         <tr>
@@ -42,23 +40,23 @@
       <tbody>
         <tr>
           <td>Born</td>
-          <td>{$query.data.birth_year}</td>
+          <td>{query.data.birth_year}</td>
         </tr>
         <tr>
           <td>Eyes</td>
-          <td>{$query.data.eye_color}</td>
+          <td>{query.data.eye_color}</td>
         </tr>
         <tr>
           <td>Hair</td>
-          <td>{$query.data.hair_color}</td>
+          <td>{query.data.hair_color}</td>
         </tr>
         <tr>
           <td>Height</td>
-          <td>{$query.data.height}</td>
+          <td>{query.data.height}</td>
         </tr>
         <tr>
           <td>Mass</td>
-          <td>{$query.data.mass}</td>
+          <td>{query.data.mass}</td>
         </tr>
         <tr>
           <td>Homeworld</td>
@@ -68,7 +66,7 @@
     </table>
     <br />
     <h4 class="text-2xl">Films</h4>
-    {#each $query.data.films as film}
+    {#each query.data.films as film}
       {@const filmUrlParts = film.split('/').filter(Boolean)}
       {@const filmId = filmUrlParts[filmUrlParts.length - 1]}
       <Film {filmId} />
diff --git a/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.ts b/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.ts
deleted file mode 100644
index dbfde8eb56..0000000000
--- a/examples/svelte/star-wars/src/routes/characters/[characterId]/+page.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { PageLoad } from './$types'
-
-export const load: PageLoad = ({ params }) => {
-  return { params }
-}
diff --git a/examples/svelte/star-wars/src/routes/characters/[characterId]/Film.svelte b/examples/svelte/star-wars/src/routes/characters/[characterId]/Film.svelte
index 7c0210d8d5..f9c7aba727 100644
--- a/examples/svelte/star-wars/src/routes/characters/[characterId]/Film.svelte
+++ b/examples/svelte/star-wars/src/routes/characters/[characterId]/Film.svelte
@@ -1,23 +1,23 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
 
-  export let filmId: string
+  let { filmId }: { filmId: string } = $props()
 
   const getFilm = async () => {
     const res = await fetch(`https://swapi.dev/api/films/${filmId}/`)
     return await res.json()
   }
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['film', filmId],
     queryFn: getFilm,
-  })
+  }))
 </script>
 
-{#if $query.status === 'success'}
+{#if query.status === 'success'}
   <article>
     <a href={`/films/${filmId}`}>
-      <h6 class="text-lg">{$query.data.episode_id}. {$query.data.title}</h6>
+      <h6 class="text-lg">{query.data.episode_id}. {query.data.title}</h6>
     </a>
   </article>
 {/if}
diff --git a/examples/svelte/star-wars/src/routes/characters/[characterId]/Homeworld.svelte b/examples/svelte/star-wars/src/routes/characters/[characterId]/Homeworld.svelte
index d931b8cc19..bde4c4cada 100644
--- a/examples/svelte/star-wars/src/routes/characters/[characterId]/Homeworld.svelte
+++ b/examples/svelte/star-wars/src/routes/characters/[characterId]/Homeworld.svelte
@@ -1,21 +1,21 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
 
-  export let homeworldId: string
+  let { homeworldId }: { homeworldId: string } = $props()
 
   const getHomeworld = async () => {
     const res = await fetch(`https://swapi.dev/api/planets/${homeworldId}/`)
     return await res.json()
   }
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['homeworld', homeworldId],
     queryFn: getHomeworld,
-  })
+  }))
 </script>
 
-{#if $query.status === 'success'}
+{#if query.status === 'success'}
   <span>
-    {$query.data.name}
+    {query.data.name}
   </span>
 {/if}
diff --git a/examples/svelte/star-wars/src/routes/films/+page.svelte b/examples/svelte/star-wars/src/routes/films/+page.svelte
index adb251e0d2..4fc29c6f50 100644
--- a/examples/svelte/star-wars/src/routes/films/+page.svelte
+++ b/examples/svelte/star-wars/src/routes/films/+page.svelte
@@ -6,24 +6,24 @@
     return await res.json()
   }
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['films'],
     queryFn: getFilms,
-  })
+  }))
 </script>
 
-{#if $query.status === 'pending'}
+{#if query.status === 'pending'}
   <p>Loading...</p>
 {/if}
 
-{#if $query.status === 'error'}
+{#if query.status === 'error'}
   <p>Error :(</p>
 {/if}
 
-{#if $query.status === 'success'}
+{#if query.status === 'success'}
   <div>
     <h2 class="text-4xl">Films</h2>
-    {#each $query.data.results as film}
+    {#each query.data.results as film}
       {@const filmUrlParts = film.url.split('/').filter(Boolean)}
       {@const filmId = filmUrlParts[filmUrlParts.length - 1]}
       <article>
diff --git a/examples/svelte/star-wars/src/routes/films/[filmId]/+page.svelte b/examples/svelte/star-wars/src/routes/films/[filmId]/+page.svelte
index 5342487a6e..47d6b69376 100644
--- a/examples/svelte/star-wars/src/routes/films/[filmId]/+page.svelte
+++ b/examples/svelte/star-wars/src/routes/films/[filmId]/+page.svelte
@@ -1,38 +1,36 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
   import Character from './Character.svelte'
-  import type { PageData } from './$types'
-
-  export let data: PageData
+  import { page } from '$app/state'
 
   const getFilm = async () => {
     const res = await fetch(
-      `https://swapi.dev/api/films/${data.params.filmId}/`,
+      `https://swapi.dev/api/films/${page.params.filmId}/`,
     )
     return await res.json()
   }
 
-  const query = createQuery({
-    queryKey: ['film', data.params.filmId],
+  const query = createQuery(() => ({
+    queryKey: ['film', page.params.filmId],
     queryFn: getFilm,
-  })
+  }))
 </script>
 
-{#if $query.status === 'pending'}
+{#if query.status === 'pending'}
   <p>Loading...</p>
 {/if}
 
-{#if $query.status === 'error'}
+{#if query.status === 'error'}
   <p>Error :(</p>
 {/if}
 
-{#if $query.status === 'success'}
+{#if query.status === 'success'}
   <div>
-    <h2 class="text-4xl">{$query.data.title}</h2>
-    <p>{$query.data.opening_crawl}</p>
+    <h2 class="text-4xl">{query.data.title}</h2>
+    <p>{query.data.opening_crawl}</p>
     <br />
     <h4 class="text-2xl">Characters</h4>
-    {#each $query.data.characters as character}
+    {#each query.data.characters as character}
       {@const characterUrlParts = character.split('/').filter(Boolean)}
       {@const characterId = characterUrlParts[characterUrlParts.length - 1]}
       <Character {characterId} />
diff --git a/examples/svelte/star-wars/src/routes/films/[filmId]/+page.ts b/examples/svelte/star-wars/src/routes/films/[filmId]/+page.ts
deleted file mode 100644
index dbfde8eb56..0000000000
--- a/examples/svelte/star-wars/src/routes/films/[filmId]/+page.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { PageLoad } from './$types'
-
-export const load: PageLoad = ({ params }) => {
-  return { params }
-}
diff --git a/examples/svelte/star-wars/src/routes/films/[filmId]/Character.svelte b/examples/svelte/star-wars/src/routes/films/[filmId]/Character.svelte
index b4827ccdf9..2b1a0ba4c9 100644
--- a/examples/svelte/star-wars/src/routes/films/[filmId]/Character.svelte
+++ b/examples/svelte/star-wars/src/routes/films/[filmId]/Character.svelte
@@ -1,23 +1,23 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
 
-  export let characterId: string
+  let { characterId }: { characterId: string } = $props()
 
   const getCharacter = async () => {
     const res = await fetch(`https://swapi.dev/api/people/${characterId}/`)
     return await res.json()
   }
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['character', characterId],
     queryFn: getCharacter,
-  })
+  }))
 </script>
 
-{#if $query.status === 'success'}
+{#if query.status === 'success'}
   <article>
     <a href={`/characters/${characterId}`}>
-      <h6 class="text-lg">{$query.data.name}</h6>
+      <h6 class="text-lg">{query.data.name}</h6>
     </a>
   </article>
 {/if}
diff --git a/examples/svelte/star-wars/svelte.config.js b/examples/svelte/star-wars/svelte.config.js
index a52aed3a7b..d6b43b0085 100644
--- a/examples/svelte/star-wars/svelte.config.js
+++ b/examples/svelte/star-wars/svelte.config.js
@@ -4,10 +4,12 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
   preprocess: vitePreprocess(),
-
   kit: {
     adapter: adapter(),
   },
+  compilerOptions: {
+    runes: true,
+  },
 }
 
 export default config
diff --git a/packages/svelte-query-devtools/package.json b/packages/svelte-query-devtools/package.json
index f636638dc5..62255dcc9a 100644
--- a/packages/svelte-query-devtools/package.json
+++ b/packages/svelte-query-devtools/package.json
@@ -54,6 +54,6 @@
   },
   "peerDependencies": {
     "@tanstack/svelte-query": "workspace:^",
-    "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0"
+    "svelte": "^5.0.0"
   }
 }
diff --git a/packages/svelte-query-devtools/src/Devtools.svelte b/packages/svelte-query-devtools/src/Devtools.svelte
index 3848004325..f83e633077 100644
--- a/packages/svelte-query-devtools/src/Devtools.svelte
+++ b/packages/svelte-query-devtools/src/Devtools.svelte
@@ -10,13 +10,50 @@
     TanstackQueryDevtools,
   } from '@tanstack/query-devtools'
 
-  export let initialIsOpen = false
-  export let buttonPosition: DevtoolsButtonPosition = 'bottom-right'
-  export let position: DevtoolsPosition = 'bottom'
-  export let client: QueryClient = useQueryClient()
-  export let errorTypes: Array<DevtoolsErrorType> = []
-  export let styleNonce: string | undefined = undefined
-  export let shadowDOMTarget: ShadowRoot | undefined = undefined
+  interface DevtoolsOptions {
+    /**
+     * Set this true if you want the dev tools to default to being open
+     */
+    initialIsOpen?: boolean
+    /**
+     * The position of the TanStack Query logo to open and close the devtools panel.
+     * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
+     * Defaults to 'bottom-right'.
+     */
+    buttonPosition?: DevtoolsButtonPosition
+    /**
+     * The position of the TanStack Query devtools panel.
+     * 'top' | 'bottom' | 'left' | 'right'
+     * Defaults to 'bottom'.
+     */
+    position?: DevtoolsPosition
+    /**
+     * Custom instance of QueryClient
+     */
+    client?: QueryClient
+    /**
+     * Use this so you can define custom errors that can be shown in the devtools.
+     */
+    errorTypes?: Array<DevtoolsErrorType>
+    /**
+     * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
+     */
+    styleNonce?: string
+    /**
+     * Use this so you can attach the devtool's styles to specific element in the DOM.
+     */
+    shadowDOMTarget?: ShadowRoot
+  }
+
+  let {
+    initialIsOpen = false,
+    buttonPosition = 'bottom-right',
+    position = 'bottom',
+    client = useQueryClient(),
+    errorTypes = [],
+    styleNonce = undefined,
+    shadowDOMTarget = undefined,
+  }: DevtoolsOptions = $props()
 
   let ref: HTMLDivElement
   let devtools: TanstackQueryDevtools | undefined
@@ -41,20 +78,24 @@
 
         devtools.mount(ref)
       })
+      return () => devtools?.unmount()
+    })
 
-      return () => {
-        devtools?.unmount()
-      }
+    $effect(() => {
+      devtools?.setButtonPosition(buttonPosition)
     })
-  }
 
-  $: {
-    if (devtools) {
-      devtools.setButtonPosition(buttonPosition)
-      devtools.setPosition(position)
-      devtools.setInitialIsOpen(initialIsOpen)
-      devtools.setErrorTypes(errorTypes)
-    }
+    $effect(() => {
+      devtools?.setPosition(position)
+    })
+
+    $effect(() => {
+      devtools?.setInitialIsOpen(initialIsOpen)
+    })
+
+    $effect(() => {
+      devtools?.setErrorTypes(errorTypes)
+    })
   }
 </script>
 
diff --git a/packages/svelte-query-persist-client/eslint.config.js b/packages/svelte-query-persist-client/eslint.config.js
index f31c5e878b..39d08afb4f 100644
--- a/packages/svelte-query-persist-client/eslint.config.js
+++ b/packages/svelte-query-persist-client/eslint.config.js
@@ -10,6 +10,7 @@ export default [
     rules: {
       'svelte/block-lang': ['error', { script: ['ts'] }],
       'svelte/no-svelte-internal': 'error',
+      'svelte/no-unused-svelte-ignore': 'off',
       'svelte/valid-compile': 'off',
     },
   },
diff --git a/packages/svelte-query-persist-client/package.json b/packages/svelte-query-persist-client/package.json
index 229e29bd96..cc3786df47 100644
--- a/packages/svelte-query-persist-client/package.json
+++ b/packages/svelte-query-persist-client/package.json
@@ -58,6 +58,6 @@
   },
   "peerDependencies": {
     "@tanstack/svelte-query": "workspace:^",
-    "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0"
+    "svelte": "^5.0.0"
   }
 }
diff --git a/packages/svelte-query-persist-client/src/PersistQueryClientProvider.svelte b/packages/svelte-query-persist-client/src/PersistQueryClientProvider.svelte
index b0ba375b04..d94c4fbe20 100644
--- a/packages/svelte-query-persist-client/src/PersistQueryClientProvider.svelte
+++ b/packages/svelte-query-persist-client/src/PersistQueryClientProvider.svelte
@@ -1,51 +1,56 @@
 <script lang="ts">
-  import { onDestroy } from 'svelte'
-  import { persistQueryClient } from '@tanstack/query-persist-client-core'
+  import {
+    persistQueryClientRestore,
+    persistQueryClientSubscribe,
+  } from '@tanstack/query-persist-client-core'
   import {
     QueryClientProvider,
     setIsRestoringContext,
   } from '@tanstack/svelte-query'
-  import { writable } from 'svelte/store'
+  import { box } from './utils.svelte.js'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
-  import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
+  import type {
+    OmitKeyof,
+    QueryClientProviderProps,
+  } from '@tanstack/svelte-query'
+
+  type PersistQueryClientProviderProps = QueryClientProviderProps & {
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    onSuccess?: () => void
+    onError?: () => void
+  }
+
+  let {
+    client,
+    children,
+    persistOptions,
+    ...props
+  }: PersistQueryClientProviderProps = $props()
 
-  export let client: QueryClient
-  export let onSuccess: () => Promise<unknown> | unknown = () => undefined
-  export let onError: () => Promise<unknown> | unknown = () => undefined
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+  let isRestoring = box(true)
 
-  const isRestoring = writable(true)
   setIsRestoringContext(isRestoring)
-  $: {
-    let isStale = false
-    isRestoring.set(true)
-    const [unsubscribe, promise] = persistQueryClient({
-      ...persistOptions,
-      queryClient: client,
-    })
-    promise
-      .then(async () => {
-        if (!isStale) {
-          await onSuccess()
-        }
-      })
-      .catch(async () => {
-        if (!isStale) {
-          await onError()
-        }
-      })
+
+  const options = $derived({
+    ...persistOptions,
+    queryClient: client,
+  })
+
+  $effect(() => {
+    return isRestoring.current ? () => {} : persistQueryClientSubscribe(options)
+  })
+
+  $effect(() => {
+    isRestoring.current = true
+    persistQueryClientRestore(options)
+      .then(() => props.onSuccess?.())
+      .catch(() => props.onError?.())
       .finally(() => {
-        if (!isStale) {
-          isRestoring.set(false)
-        }
+        isRestoring.current = false
       })
-    onDestroy(() => {
-      isStale = true
-      unsubscribe()
-    })
-  }
+  })
 </script>
 
-<QueryClientProvider {client}>
-  <slot />
+<QueryClientProvider {client} {...props}>
+  {@render children()}
 </QueryClientProvider>
diff --git a/packages/svelte-query-persist-client/src/utils.svelte.ts b/packages/svelte-query-persist-client/src/utils.svelte.ts
new file mode 100644
index 0000000000..7760eded8c
--- /dev/null
+++ b/packages/svelte-query-persist-client/src/utils.svelte.ts
@@ -0,0 +1,14 @@
+type Box<T> = { current: T }
+
+export function box<T>(initial: T): Box<T> {
+  let current = $state(initial)
+
+  return {
+    get current() {
+      return current
+    },
+    set current(newValue) {
+      current = newValue
+    },
+  }
+}
diff --git a/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte b/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte
index 74f09accd8..585211e194 100644
--- a/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte
+++ b/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte
@@ -1,20 +1,20 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
   import { sleep } from '@tanstack/query-test-utils'
-  import type { Writable } from 'svelte/store'
+  import { sleep, StatelessRef } from '../utils.svelte.js'
 
-  export let states: Writable<Array<string>>
+  let { states }: { states: StatelessRef<Array<string>> } = $props()
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['test'],
     queryFn: async () => {
-      states.update((s) => [...s, 'fetching'])
+      states.current.push('fetching')
       await sleep(5)
-      states.update((s) => [...s, 'fetched'])
+      states.current.push('fetched')
       return 'fetched'
     },
-  })
+  }))
 </script>
 
-<div>{$query.data}</div>
-<div>fetchStatus: {$query.fetchStatus}</div>
+<div>{query.data}</div>
+<div>fetchStatus: {query.fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/AwaitOnSuccess/Provider.svelte b/packages/svelte-query-persist-client/tests/AwaitOnSuccess/Provider.svelte
index c3087ac2fa..79126c724b 100644
--- a/packages/svelte-query-persist-client/tests/AwaitOnSuccess/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/AwaitOnSuccess/Provider.svelte
@@ -3,12 +3,16 @@
   import AwaitOnSuccess from './AwaitOnSuccess.svelte'
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
-  import type { Writable } from 'svelte/store'
+  import { StatelessRef } from '../utils.svelte'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let onSuccess: () => Promise<void>
-  export let states: Writable<Array<string>>
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    onSuccess: () => Promise<void>
+    states: StatelessRef<Array<string>>
+  }
+
+  let { queryClient, persistOptions, onSuccess, states }: Props = $props()
 </script>
 
 <PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>
diff --git a/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte b/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte
index 451a2a98f2..fff8ba820d 100644
--- a/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte
+++ b/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte
@@ -1,25 +1,26 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let states: Writable<Array<StatusResult<string>>>
-  export let fetched: Writable<boolean>
+  let {
+    states,
+  }: {
+    states: StatelessRef<Array<StatusResult<string>>>
+  } = $props()
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['test'],
-    queryFn: async () => {
-      fetched.set(true)
-      await sleep(5)
-      return 'fetched'
-    },
+    queryFn: () => Promise.resolve('fetched'),
 
     staleTime: Infinity,
-  })
+  }))
 
-  $: states.update((prev) => [...prev, $query])
+  $effect(() => {
+    // svelte-ignore state_snapshot_uncloneable
+    const snapshot = $state.snapshot(query)
+    states.current.push(snapshot)
+  })
 </script>
 
-<div>data: {$query.data ?? 'undefined'}</div>
-<div>fetchStatus: {$query.fetchStatus}</div>
+<div>data: {query.data ?? 'undefined'}</div>
+<div>fetchStatus: {query.fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/FreshData/Provider.svelte b/packages/svelte-query-persist-client/tests/FreshData/Provider.svelte
index 75a9c1aefa..70a9ea483f 100644
--- a/packages/svelte-query-persist-client/tests/FreshData/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/FreshData/Provider.svelte
@@ -3,15 +3,17 @@
   import FreshData from './FreshData.svelte'
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let states: Writable<Array<StatusResult<string>>>
-  export let fetched: Writable<boolean>
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    states: StatelessRef<Array<StatusResult<string>>>
+  }
+
+  let { queryClient, persistOptions, states }: Props = $props()
 </script>
 
 <PersistQueryClientProvider client={queryClient} {persistOptions}>
-  <FreshData {states} {fetched} />
+  <FreshData {states} />
 </PersistQueryClientProvider>
diff --git a/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte b/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte
index 7e661dbe71..a4df9132f8 100644
--- a/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte
+++ b/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte
@@ -1,12 +1,12 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
   import { sleep } from '@tanstack/query-test-utils'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let states: Writable<Array<StatusResult<string>>>
+  let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =
+    $props()
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['test'],
     queryFn: async () => {
       await sleep(5)
@@ -17,10 +17,14 @@
     // make sure that initial data is older than the hydration data
     // otherwise initialData would be newer and takes precedence
     initialDataUpdatedAt: 1,
-  })
+  }))
 
-  $: states.update((prev) => [...prev, $query])
+  $effect(() => {
+    // svelte-ignore state_snapshot_uncloneable
+    const snapshot = $state.snapshot(query)
+    states.current.push(snapshot)
+  })
 </script>
 
-<div>{$query.data}</div>
-<div>fetchStatus: {$query.fetchStatus}</div>
+<div>{query.data}</div>
+<div>fetchStatus: {query.fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/InitialData/Provider.svelte b/packages/svelte-query-persist-client/tests/InitialData/Provider.svelte
index e5e17f712e..a50338006a 100644
--- a/packages/svelte-query-persist-client/tests/InitialData/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/InitialData/Provider.svelte
@@ -3,12 +3,15 @@
   import InitialData from './InitialData.svelte'
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let states: Writable<Array<StatusResult<string>>>
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    states: StatelessRef<Array<StatusResult<string>>>
+  }
+
+  let { queryClient, persistOptions, states }: Props = $props()
 </script>
 
 <PersistQueryClientProvider client={queryClient} {persistOptions}>
diff --git a/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte b/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte
index 40dd1d90be..a6ef7b3214 100644
--- a/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte
+++ b/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte
@@ -1,15 +1,11 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
-  import { sleep } from '@tanstack/query-test-utils'
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['test'],
-    queryFn: async () => {
-      await sleep(5)
-      return 'fetched'
-    },
-  })
+    queryFn: () => Promise.resolve('fetched'),
+  }))
 </script>
 
-<div>{$query.data}</div>
-<div>fetchStatus: {$query.fetchStatus}</div>
+<div>{query.data}</div>
+<div>fetchStatus: {query.fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/OnSuccess/Provider.svelte b/packages/svelte-query-persist-client/tests/OnSuccess/Provider.svelte
index c0d2792771..0b280ca570 100644
--- a/packages/svelte-query-persist-client/tests/OnSuccess/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/OnSuccess/Provider.svelte
@@ -4,9 +4,13 @@
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let onSuccess: () => void
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    onSuccess: () => void
+  }
+
+  let { queryClient, persistOptions, onSuccess }: Props = $props()
 </script>
 
 <PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>
diff --git a/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts b/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.svelte.test.ts
similarity index 73%
rename from packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts
rename to packages/svelte-query-persist-client/tests/PersistQueryClientProvider.svelte.test.ts
index a6f3105c63..078e409967 100644
--- a/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts
+++ b/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.svelte.test.ts
@@ -1,9 +1,7 @@
 import { render, waitFor } from '@testing-library/svelte'
 import { describe, expect, test, vi } from 'vitest'
 import { persistQueryClientSave } from '@tanstack/query-persist-client-core'
-import { get, writable } from 'svelte/store'
 import { sleep } from '@tanstack/query-test-utils'
-import { QueryClient } from '@tanstack/svelte-query'
 import AwaitOnSuccess from './AwaitOnSuccess/Provider.svelte'
 import FreshData from './FreshData/Provider.svelte'
 import OnSuccess from './OnSuccess/Provider.svelte'
@@ -11,13 +9,12 @@ import InitialData from './InitialData/Provider.svelte'
 import RemoveCache from './RemoveCache/Provider.svelte'
 import RestoreCache from './RestoreCache/Provider.svelte'
 import UseQueries from './UseQueries/Provider.svelte'
-
+import { StatelessRef, createQueryClient } from './utils.svelte.js'
 import type {
   PersistedClient,
   Persister,
 } from '@tanstack/query-persist-client-core'
-import type { Writable } from 'svelte/store'
-import type { StatusResult } from './utils.js'
+import type { StatusResult } from './utils.svelte.js'
 
 const createMockPersister = (): Persister => {
   let storedState: PersistedClient | undefined
@@ -27,8 +24,7 @@ const createMockPersister = (): Persister => {
       storedState = persistClient
     },
     async restoreClient() {
-      await sleep(5)
-      return storedState
+      return Promise.resolve(storedState)
     },
     removeClient() {
       storedState = undefined
@@ -47,8 +43,7 @@ const createMockErrorPersister = (
         // noop
       },
       async restoreClient() {
-        await sleep(5)
-        throw error
+        return Promise.reject(error)
       },
       removeClient,
     },
@@ -57,7 +52,7 @@ const createMockErrorPersister = (
 
 describe('PersistQueryClientProvider', () => {
   test('restores cache from persister', async () => {
-    const statesStore: Writable<Array<StatusResult<string>>> = writable([])
+    const states = new StatelessRef<Array<StatusResult<string>>>([])
 
     const queryClient = new QueryClient()
     await queryClient.prefetchQuery({
@@ -75,7 +70,7 @@ describe('PersistQueryClientProvider', () => {
       props: {
         queryClient,
         persistOptions: { persister },
-        states: statesStore,
+        states,
       },
     })
 
@@ -83,34 +78,21 @@ describe('PersistQueryClientProvider', () => {
     await waitFor(() => rendered.getByText('hydrated'))
     await waitFor(() => rendered.getByText('fetched'))
 
-    const states = get(statesStore)
-    expect(states).toHaveLength(5)
+    expect(states.current).toHaveLength(3)
 
-    expect(states[0]).toMatchObject({
+    expect(states.current[0]).toMatchObject({
       status: 'pending',
       fetchStatus: 'idle',
       data: undefined,
     })
 
-    expect(states[1]).toMatchObject({
-      status: 'success',
-      fetchStatus: 'fetching',
-      data: 'hydrated',
-    })
-
-    expect(states[2]).toMatchObject({
+    expect(states.current[1]).toMatchObject({
       status: 'success',
       fetchStatus: 'fetching',
       data: 'hydrated',
     })
 
-    expect(states[3]).toMatchObject({
-      status: 'success',
-      fetchStatus: 'fetching',
-      data: 'hydrated',
-    })
-
-    expect(states[4]).toMatchObject({
+    expect(states.current[2]).toMatchObject({
       status: 'success',
       fetchStatus: 'idle',
       data: 'fetched',
@@ -118,7 +100,7 @@ describe('PersistQueryClientProvider', () => {
   })
 
   test('should also put useQueries into idle state', async () => {
-    const statesStore: Writable<Array<StatusResult<string>>> = writable([])
+    const states = new StatelessRef<Array<StatusResult<string>>>([])
 
     const queryClient = new QueryClient()
     await queryClient.prefetchQuery({
@@ -136,7 +118,7 @@ describe('PersistQueryClientProvider', () => {
       props: {
         queryClient,
         persistOptions: { persister },
-        states: statesStore,
+        states,
       },
     })
 
@@ -144,35 +126,21 @@ describe('PersistQueryClientProvider', () => {
     await waitFor(() => rendered.getByText('hydrated'))
     await waitFor(() => rendered.getByText('fetched'))
 
-    const states = get(statesStore)
-
-    expect(states).toHaveLength(5)
+    expect(states.current).toHaveLength(3)
 
-    expect(states[0]).toMatchObject({
+    expect(states.current[0]).toMatchObject({
       status: 'pending',
       fetchStatus: 'idle',
       data: undefined,
     })
 
-    expect(states[1]).toMatchObject({
+    expect(states.current[1]).toMatchObject({
       status: 'success',
       fetchStatus: 'fetching',
       data: 'hydrated',
     })
 
-    expect(states[2]).toMatchObject({
-      status: 'success',
-      fetchStatus: 'fetching',
-      data: 'hydrated',
-    })
-
-    expect(states[3]).toMatchObject({
-      status: 'success',
-      fetchStatus: 'fetching',
-      data: 'hydrated',
-    })
-
-    expect(states[4]).toMatchObject({
+    expect(states.current[2]).toMatchObject({
       status: 'success',
       fetchStatus: 'idle',
       data: 'fetched',
@@ -180,7 +148,7 @@ describe('PersistQueryClientProvider', () => {
   })
 
   test('should show initialData while restoring', async () => {
-    const statesStore: Writable<Array<StatusResult<string>>> = writable([])
+    const states = new StatelessRef<Array<StatusResult<string>>>([])
 
     const queryClient = new QueryClient()
     await queryClient.prefetchQuery({
@@ -198,7 +166,7 @@ describe('PersistQueryClientProvider', () => {
       props: {
         queryClient,
         persistOptions: { persister },
-        states: statesStore,
+        states,
       },
     })
 
@@ -206,34 +174,21 @@ describe('PersistQueryClientProvider', () => {
     await waitFor(() => rendered.getByText('hydrated'))
     await waitFor(() => rendered.getByText('fetched'))
 
-    const states = get(statesStore)
-    expect(states).toHaveLength(5)
+    expect(states.current).toHaveLength(3)
 
-    expect(states[0]).toMatchObject({
+    expect(states.current[0]).toMatchObject({
       status: 'success',
       fetchStatus: 'idle',
       data: 'initial',
     })
 
-    expect(states[1]).toMatchObject({
-      status: 'success',
-      fetchStatus: 'fetching',
-      data: 'hydrated',
-    })
-
-    expect(states[2]).toMatchObject({
-      status: 'success',
-      fetchStatus: 'fetching',
-      data: 'hydrated',
-    })
-
-    expect(states[3]).toMatchObject({
+    expect(states.current[1]).toMatchObject({
       status: 'success',
       fetchStatus: 'fetching',
       data: 'hydrated',
     })
 
-    expect(states[4]).toMatchObject({
+    expect(states.current[2]).toMatchObject({
       status: 'success',
       fetchStatus: 'idle',
       data: 'fetched',
@@ -241,7 +196,7 @@ describe('PersistQueryClientProvider', () => {
   })
 
   test('should not refetch after restoring when data is fresh', async () => {
-    const statesStore: Writable<Array<StatusResult<string>>> = writable([])
+    const states = new StatelessRef<Array<StatusResult<string>>>([])
 
     const queryClient = new QueryClient()
     await queryClient.prefetchQuery({
@@ -255,32 +210,31 @@ describe('PersistQueryClientProvider', () => {
 
     queryClient.clear()
 
-    const fetched = writable(false)
-
     const rendered = render(FreshData, {
       props: {
         queryClient,
         persistOptions: { persister },
-        states: statesStore,
-        fetched,
+        states,
       },
     })
 
     await waitFor(() => rendered.getByText('data: undefined'))
     await waitFor(() => rendered.getByText('data: hydrated'))
+    await expect(
+      waitFor(() => rendered.getByText('data: fetched'), {
+        timeout: 100,
+      }),
+    ).rejects.toThrowError()
 
-    const states = get(statesStore)
-    expect(states).toHaveLength(2)
+    expect(states.current).toHaveLength(2)
 
-    expect(get(fetched)).toBe(false)
-
-    expect(states[0]).toMatchObject({
+    expect(states.current[0]).toMatchObject({
       status: 'pending',
       fetchStatus: 'idle',
       data: undefined,
     })
 
-    expect(states[1]).toMatchObject({
+    expect(states.current[1]).toMatchObject({
       status: 'success',
       fetchStatus: 'idle',
       data: 'hydrated',
@@ -311,7 +265,6 @@ describe('PersistQueryClientProvider', () => {
     })
 
     expect(onSuccess).toHaveBeenCalledTimes(0)
-
     await waitFor(() => rendered.getByText('hydrated'))
     expect(onSuccess).toHaveBeenCalledTimes(1)
     await waitFor(() => rendered.getByText('fetched'))
@@ -330,17 +283,17 @@ describe('PersistQueryClientProvider', () => {
 
     queryClient.clear()
 
-    const statesStore: Writable<Array<string>> = writable([])
+    const states = new StatelessRef<Array<string>>([])
 
     const rendered = render(AwaitOnSuccess, {
       props: {
         queryClient,
         persistOptions: { persister },
-        states: statesStore,
+        states,
         onSuccess: async () => {
-          statesStore.update((s) => [...s, 'onSuccess'])
-          await sleep(20)
-          statesStore.update((s) => [...s, 'onSuccess done'])
+          states.current.push('onSuccess')
+          await sleep(5)
+          states.current.push('onSuccess done')
         },
       },
     })
@@ -348,9 +301,7 @@ describe('PersistQueryClientProvider', () => {
     await waitFor(() => rendered.getByText('hydrated'))
     await waitFor(() => rendered.getByText('fetched'))
 
-    const states = get(statesStore)
-
-    expect(states).toEqual([
+    expect(states.current).toEqual([
       'onSuccess',
       'onSuccess done',
       'fetching',
@@ -359,11 +310,12 @@ describe('PersistQueryClientProvider', () => {
   })
 
   test('should remove cache after non-successful restoring', async () => {
-    const consoleMock = vi.spyOn(console, 'error')
+    const consoleMock = vi
+      .spyOn(console, 'error')
+      .mockImplementation(() => undefined)
     const consoleWarn = vi
       .spyOn(console, 'warn')
       .mockImplementation(() => undefined)
-    consoleMock.mockImplementation(() => undefined)
 
     const queryClient = new QueryClient()
     const removeClient = vi.fn()
diff --git a/packages/svelte-query-persist-client/tests/RemoveCache/Provider.svelte b/packages/svelte-query-persist-client/tests/RemoveCache/Provider.svelte
index 7edd6cc903..c6410d912e 100644
--- a/packages/svelte-query-persist-client/tests/RemoveCache/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/RemoveCache/Provider.svelte
@@ -4,10 +4,14 @@
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let onSuccess: () => void
-  export let onError: () => void
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    onSuccess: () => void
+    onError: () => void
+  }
+
+  let { queryClient, persistOptions, onError, onSuccess }: Props = $props()
 </script>
 
 <PersistQueryClientProvider
diff --git a/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte b/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte
index 40dd1d90be..a6ef7b3214 100644
--- a/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte
+++ b/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte
@@ -1,15 +1,11 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
-  import { sleep } from '@tanstack/query-test-utils'
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['test'],
-    queryFn: async () => {
-      await sleep(5)
-      return 'fetched'
-    },
-  })
+    queryFn: () => Promise.resolve('fetched'),
+  }))
 </script>
 
-<div>{$query.data}</div>
-<div>fetchStatus: {$query.fetchStatus}</div>
+<div>{query.data}</div>
+<div>fetchStatus: {query.fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/RestoreCache/Provider.svelte b/packages/svelte-query-persist-client/tests/RestoreCache/Provider.svelte
index 531aae8c3f..e89cdbafef 100644
--- a/packages/svelte-query-persist-client/tests/RestoreCache/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/RestoreCache/Provider.svelte
@@ -3,12 +3,15 @@
   import RestoreCache from './RestoreCache.svelte'
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let states: Writable<Array<StatusResult<string>>>
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    states: StatelessRef<Array<StatusResult<string>>>
+  }
+
+  let { queryClient, persistOptions, states }: Props = $props()
 </script>
 
 <PersistQueryClientProvider client={queryClient} {persistOptions}>
diff --git a/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte b/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte
index de78c98bfd..79b9b6add5 100644
--- a/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte
+++ b/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte
@@ -1,21 +1,21 @@
 <script lang="ts">
   import { createQuery } from '@tanstack/svelte-query'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let states: Writable<Array<StatusResult<string>>>
+  let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =
+    $props()
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['test'],
-    queryFn: async () => {
-      await sleep(5)
-      return 'fetched'
-    },
-  })
+    queryFn: async () => Promise.resolve('fetched'),
+  }))
 
-  $: states.update((prev) => [...prev, $query])
+  $effect(() => {
+    // svelte-ignore state_snapshot_uncloneable
+    const snapshot = $state.snapshot(query)
+    states.current.push(snapshot)
+  })
 </script>
 
-<div>{$query.data}</div>
-<div>fetchStatus: {$query.fetchStatus}</div>
+<div>{query.data}</div>
+<div>fetchStatus: {query.fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/UseQueries/Provider.svelte b/packages/svelte-query-persist-client/tests/UseQueries/Provider.svelte
index 56429b7d81..b5a3857bf7 100644
--- a/packages/svelte-query-persist-client/tests/UseQueries/Provider.svelte
+++ b/packages/svelte-query-persist-client/tests/UseQueries/Provider.svelte
@@ -3,12 +3,15 @@
   import UseQueries from './UseQueries.svelte'
   import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
   import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let queryClient: QueryClient
-  export let persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
-  export let states: Writable<Array<StatusResult<string>>>
+  interface Props {
+    queryClient: QueryClient
+    persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
+    states: StatelessRef<Array<StatusResult<string>>>
+  }
+
+  let { queryClient, persistOptions, states }: Props = $props()
 </script>
 
 <PersistQueryClientProvider client={queryClient} {persistOptions}>
diff --git a/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte b/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte
index 15b5ab46ff..4d646ac8cf 100644
--- a/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte
+++ b/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte
@@ -1,25 +1,25 @@
 <script lang="ts">
   import { createQueries } from '@tanstack/svelte-query'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { Writable } from 'svelte/store'
-  import type { StatusResult } from '../utils.js'
+  import type { StatelessRef, StatusResult } from '../utils.svelte.js'
 
-  export let states: Writable<Array<StatusResult<string>>>
+  let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =
+    $props()
 
-  const queries = createQueries({
+  const queries = createQueries(() => ({
     queries: [
       {
         queryKey: ['test'],
-        queryFn: async (): Promise<string> => {
-          await sleep(5)
-          return 'fetched'
-        },
+        queryFn: () => Promise.resolve('fetched'),
       },
     ],
-  })
+  }))
 
-  $: states.update((prev) => [...prev, $queries[0]])
+  $effect(() => {
+    // svelte-ignore state_snapshot_uncloneable
+    const snapshot = $state.snapshot(queries[0])
+    states.current.push(snapshot)
+  })
 </script>
 
-<div>{$queries[0].data}</div>
-<div>fetchStatus: {$queries[0].fetchStatus}</div>
+<div>{queries[0].data}</div>
+<div>fetchStatus: {queries[0].fetchStatus}</div>
diff --git a/packages/svelte-query-persist-client/tests/utils.ts b/packages/svelte-query-persist-client/tests/utils.svelte.ts
similarity index 50%
rename from packages/svelte-query-persist-client/tests/utils.ts
rename to packages/svelte-query-persist-client/tests/utils.svelte.ts
index bf757da058..47162efdea 100644
--- a/packages/svelte-query-persist-client/tests/utils.ts
+++ b/packages/svelte-query-persist-client/tests/utils.svelte.ts
@@ -3,3 +3,10 @@ export type StatusResult<T = unknown> = {
   fetchStatus: string
   data: T | undefined
 }
+
+export class StatelessRef<T> {
+  current: T
+  constructor(value: T) {
+    this.current = value
+  }
+}
diff --git a/packages/svelte-query-persist-client/vite.config.ts b/packages/svelte-query-persist-client/vite.config.ts
index 1249fcc5a8..fd7a429728 100644
--- a/packages/svelte-query-persist-client/vite.config.ts
+++ b/packages/svelte-query-persist-client/vite.config.ts
@@ -23,7 +23,6 @@ export default defineConfig({
     watch: false,
     environment: 'jsdom',
     setupFiles: ['./tests/test-setup.ts'],
-    coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] },
     typecheck: { enabled: true },
     restoreMocks: true,
   },
diff --git a/packages/svelte-query/eslint.config.js b/packages/svelte-query/eslint.config.js
index f31c5e878b..39d08afb4f 100644
--- a/packages/svelte-query/eslint.config.js
+++ b/packages/svelte-query/eslint.config.js
@@ -10,6 +10,7 @@ export default [
     rules: {
       'svelte/block-lang': ['error', { script: ['ts'] }],
       'svelte/no-svelte-internal': 'error',
+      'svelte/no-unused-svelte-ignore': 'off',
       'svelte/valid-compile': 'off',
     },
   },
diff --git a/packages/svelte-query/package.json b/packages/svelte-query/package.json
index 697b825bcc..e22497e019 100644
--- a/packages/svelte-query/package.json
+++ b/packages/svelte-query/package.json
@@ -14,6 +14,12 @@
     "type": "github",
     "url": "https://github.com/sponsors/tannerlinsley"
   },
+  "keywords": [
+    "tanstack",
+    "query",
+    "svelte",
+    "swr"
+  ],
   "scripts": {
     "clean": "premove ./dist ./coverage ./.svelte-kit ./dist-ts",
     "compile": "tsc --build",
@@ -56,6 +62,6 @@
     "svelte-check": "^4.1.5"
   },
   "peerDependencies": {
-    "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0"
+    "svelte": "^5.7.0"
   }
 }
diff --git a/packages/svelte-query/src/HydrationBoundary.svelte b/packages/svelte-query/src/HydrationBoundary.svelte
index 330984311f..96c26068a2 100644
--- a/packages/svelte-query/src/HydrationBoundary.svelte
+++ b/packages/svelte-query/src/HydrationBoundary.svelte
@@ -1,16 +1,27 @@
 <script lang="ts">
   import { useHydrate } from './useHydrate.js'
+  import type { Snippet } from 'svelte'
   import type {
     DehydratedState,
     HydrateOptions,
     QueryClient,
   } from '@tanstack/query-core'
 
-  export let state: DehydratedState
-  export let options: HydrateOptions | undefined = undefined
-  export let queryClient: QueryClient | undefined = undefined
+  type Props = {
+    children: Snippet
+    state: DehydratedState
+    options: HydrateOptions | undefined
+    queryClient: QueryClient | undefined
+  }
+
+  const {
+    children,
+    state,
+    options = undefined,
+    queryClient = undefined,
+  }: Props = $props()
 
   useHydrate(state, options, queryClient)
 </script>
 
-<slot />
+{@render children()}
diff --git a/packages/svelte-query/src/QueryClientProvider.svelte b/packages/svelte-query/src/QueryClientProvider.svelte
index 9f43e49093..36f1df43b1 100644
--- a/packages/svelte-query/src/QueryClientProvider.svelte
+++ b/packages/svelte-query/src/QueryClientProvider.svelte
@@ -2,8 +2,10 @@
   import { onDestroy, onMount } from 'svelte'
   import { QueryClient } from '@tanstack/query-core'
   import { setQueryClientContext } from './context.js'
+  import type { QueryClientProviderProps } from './types.js'
 
-  export let client = new QueryClient()
+  const { client = new QueryClient(), children }: QueryClientProviderProps =
+    $props()
 
   onMount(() => {
     client.mount()
@@ -16,4 +18,4 @@
   })
 </script>
 
-<slot />
+{@render children()}
diff --git a/packages/svelte-query/src/containers.svelte.ts b/packages/svelte-query/src/containers.svelte.ts
new file mode 100644
index 0000000000..080a9092e8
--- /dev/null
+++ b/packages/svelte-query/src/containers.svelte.ts
@@ -0,0 +1,123 @@
+import { createSubscriber } from 'svelte/reactivity'
+
+type VoidFn = () => void
+type Subscriber = (update: VoidFn) => void | VoidFn
+
+export type Box<T> = { current: T }
+
+export class ReactiveValue<T> implements Box<T> {
+  #fn
+  #subscribe
+
+  constructor(fn: () => T, onSubscribe: Subscriber) {
+    this.#fn = fn
+    this.#subscribe = createSubscriber((update) => onSubscribe(update))
+  }
+
+  get current() {
+    this.#subscribe()
+    return this.#fn()
+  }
+}
+
+/**
+ * Makes all of the top-level keys of an object into $state.raw fields whose initial values
+ * are the same as in the original object. Does not mutate the original object. Provides an `update`
+ * function that _can_ (but does not have to be) be used to replace all of the object's top-level keys
+ * with the values of the new object, while maintaining the original root object's reference.
+ */
+export function createRawRef<T extends {} | Array<unknown>>(
+  init: T,
+): [T, (newValue: T) => void] {
+  const refObj = (Array.isArray(init) ? [] : {}) as T
+  const hiddenKeys = new Set<PropertyKey>()
+  const out = new Proxy(refObj, {
+    set(target, prop, value, receiver) {
+      hiddenKeys.delete(prop)
+      if (prop in target) {
+        return Reflect.set(target, prop, value, receiver)
+      }
+      let state = $state.raw(value)
+      Object.defineProperty(target, prop, {
+        configurable: true,
+        enumerable: true,
+        get: () => {
+          // If this is a lazy value, we need to call it.
+          // We can't do something like typeof state === 'function'
+          // because the value could actually be a function that we don't want to call.
+          return state && isBranded(state) ? state() : state
+        },
+        set: (v) => {
+          state = v
+        },
+      })
+      return true
+    },
+    has: (target, prop) => {
+      if (hiddenKeys.has(prop)) {
+        return false
+      }
+      return prop in target
+    },
+    ownKeys(target) {
+      return Reflect.ownKeys(target).filter((key) => !hiddenKeys.has(key))
+    },
+    getOwnPropertyDescriptor(target, prop) {
+      if (hiddenKeys.has(prop)) {
+        return undefined
+      }
+      return Reflect.getOwnPropertyDescriptor(target, prop)
+    },
+    deleteProperty(target, prop) {
+      if (prop in target) {
+        // @ts-expect-error
+        // We need to set the value to undefined to signal to the listeners that the value has changed.
+        // If we just deleted it, the reactivity system wouldn't have any idea that the value was gone.
+        target[prop] = undefined
+        hiddenKeys.add(prop)
+        if (Array.isArray(target)) {
+          target.length--
+        }
+        return true
+      }
+      return false
+    },
+  })
+
+  function update(newValue: T) {
+    const existingKeys = Object.keys(out)
+    const newKeys = Object.keys(newValue)
+    const keysToRemove = existingKeys.filter((key) => !newKeys.includes(key))
+    for (const key of keysToRemove) {
+      // @ts-expect-error
+      delete out[key]
+    }
+    for (const key of newKeys) {
+      // @ts-expect-error
+      // This craziness is required because Tanstack Query defines getters for all of the keys on the object.
+      // These getters track property access, so if we access all of them here, we'll end up tracking everything.
+      // So we wrap the property access in a special function that we can identify later to lazily access the value.
+      // (See above)
+      out[key] = brand(() => newValue[key])
+    }
+  }
+
+  // we can't pass `init` directly into the proxy because it'll never set the state fields
+  // (because (prop in target) will always be true)
+  update(init)
+
+  return [out, update]
+}
+
+const lazyBrand = Symbol('LazyValue')
+type Branded<T extends () => unknown> = T & { [lazyBrand]: true }
+
+function brand<T extends () => unknown>(fn: T): Branded<T> {
+  // @ts-expect-error
+  fn[lazyBrand] = true
+  return fn as Branded<T>
+}
+
+function isBranded<T extends () => unknown>(fn: T): fn is Branded<T> {
+  return Boolean((fn as Branded<T>)[lazyBrand])
+}
diff --git a/packages/svelte-query/src/context.ts b/packages/svelte-query/src/context.ts
index 962451b232..27595517f5 100644
--- a/packages/svelte-query/src/context.ts
+++ b/packages/svelte-query/src/context.ts
@@ -1,20 +1,19 @@
 import { getContext, setContext } from 'svelte'
-import { readable } from 'svelte/store'
 import type { QueryClient } from '@tanstack/query-core'
-import type { Readable } from 'svelte/store'
+import type { Box } from './containers.svelte'
 
-const _contextKey = '$$_queryClient'
+const _contextKey = Symbol('QueryClient')
 
 /** Retrieves a Client from Svelte's context */
 export const getQueryClientContext = (): QueryClient => {
-  const client = getContext(_contextKey)
+  const client = getContext<QueryClient | undefined>(_contextKey)
   if (!client) {
     throw new Error(
       'No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?',
     )
   }
 
-  return client as QueryClient
+  return client
 }
 
 /** Sets a QueryClient on Svelte's context */
@@ -22,21 +21,21 @@ export const setQueryClientContext = (client: QueryClient): void => {
   setContext(_contextKey, client)
 }
 
-const _isRestoringContextKey = '$$_isRestoring'
+const _isRestoringContextKey = Symbol('isRestoring')
 
 /** Retrieves a `isRestoring` from Svelte's context */
-export const getIsRestoringContext = (): Readable<boolean> => {
+export const getIsRestoringContext = (): Box<boolean> => {
   try {
-    const isRestoring = getContext<Readable<boolean> | undefined>(
+    const isRestoring = getContext<Box<boolean> | undefined>(
       _isRestoringContextKey,
     )
-    return isRestoring ? isRestoring : readable(false)
+    return isRestoring ?? { current: false }
   } catch (error) {
-    return readable(false)
+    return { current: false }
   }
 }
 
 /** Sets a `isRestoring` on Svelte's context */
-export const setIsRestoringContext = (isRestoring: Readable<boolean>): void => {
+export const setIsRestoringContext = (isRestoring: Box<boolean>): void => {
   setContext(_isRestoringContextKey, isRestoring)
 }
diff --git a/packages/svelte-query/src/createBaseQuery.svelte.ts b/packages/svelte-query/src/createBaseQuery.svelte.ts
new file mode 100644
index 0000000000..8307f5e40f
--- /dev/null
+++ b/packages/svelte-query/src/createBaseQuery.svelte.ts
@@ -0,0 +1,83 @@
+import { untrack } from 'svelte'
+import { useIsRestoring } from './useIsRestoring.js'
+import { useQueryClient } from './useQueryClient.js'
+import { createRawRef } from './containers.svelte.js'
+import type { QueryClient, QueryKey, QueryObserver } from '@tanstack/query-core'
+import type {
+  Accessor,
+  CreateBaseQueryOptions,
+  CreateBaseQueryResult,
+} from './types.js'
+
+/**
+ * Base implementation for `createQuery` and `createInfiniteQuery`
+ * @param options - A function that returns query options
+ * @param Observer - The observer from query-core
+ * @param queryClient - Custom query client which overrides provider
+ */
+export function createBaseQuery<
+  TQueryFnData,
+  TError,
+  TData,
+  TQueryData,
+  TQueryKey extends QueryKey,
+>(
+  options: Accessor<
+    CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>
+  >,
+  Observer: typeof QueryObserver,
+  queryClient?: Accessor<QueryClient>,
+): CreateBaseQueryResult<TData, TError> {
+  /** Load query client */
+  const client = $derived(useQueryClient(queryClient?.()))
+  const isRestoring = useIsRestoring()
+
+  const resolvedOptions = $derived.by(() => {
+    const opts = client.defaultQueryOptions(options())
+    opts._optimisticResults = isRestoring.current ? 'isRestoring' : 'optimistic'
+    return opts
+  })
+
+  /** Creates the observer */
+  const observer = $derived(
+    new Observer<TQueryFnData, TError, TData, TQueryData, TQueryKey>(
+      client,
+      untrack(() => resolvedOptions),
+    ),
+  )
+
+  function createResult() {
+    const result = observer.getOptimisticResult(resolvedOptions)
+    return !resolvedOptions.notifyOnChangeProps
+      ? observer.trackResult(result)
+      : result
+  }
+  const [query, update] = createRawRef(
+    // svelte-ignore state_referenced_locally - intentional, initial value
+    createResult(),
+  )
+
+  $effect(() => {
+    const unsubscribe = isRestoring.current
+      ? () => undefined
+      : observer.subscribe(() => update(createResult()))
+    observer.updateResult()
+    return unsubscribe
+  })
+
+  $effect.pre(() => {
+    observer.setOptions(resolvedOptions)
+    // The only reason this is necessary is because of `isRestoring`.
+    // Because we don't subscribe while restoring, the following can occur:
+    // - `isRestoring` is true
+    // - `isRestoring` becomes false
+    // - `observer.subscribe` and `observer.updateResult` is called in the above effect,
+    //   but the subsequent `fetch` has already completed
+    // - `result` misses the intermediate restored-but-not-fetched state
+    //
+    // this could technically be its own effect but that doesn't seem necessary
+    update(createResult())
+  })
+
+  return query
+}
diff --git a/packages/svelte-query/src/createBaseQuery.ts b/packages/svelte-query/src/createBaseQuery.ts
deleted file mode 100644
index acd81bdd8c..0000000000
--- a/packages/svelte-query/src/createBaseQuery.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { derived, get, readable } from 'svelte/store'
-import { notifyManager } from '@tanstack/query-core'
-import { useIsRestoring } from './useIsRestoring.js'
-import { useQueryClient } from './useQueryClient.js'
-import { isSvelteStore, noop } from './utils.js'
-import type {
-  QueryClient,
-  QueryKey,
-  QueryObserver,
-  QueryObserverResult,
-} from '@tanstack/query-core'
-import type {
-  CreateBaseQueryOptions,
-  CreateBaseQueryResult,
-  StoreOrVal,
-} from './types.js'
-
-export function createBaseQuery<
-  TQueryFnData,
-  TError,
-  TData,
-  TQueryData,
-  TQueryKey extends QueryKey,
->(
-  options: StoreOrVal<
-    CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>
-  >,
-  Observer: typeof QueryObserver,
-  queryClient?: QueryClient,
-): CreateBaseQueryResult<TData, TError> {
-  /** Load query client */
-  const client = useQueryClient(queryClient)
-  const isRestoring = useIsRestoring()
-  /** Converts options to a svelte store if not already a store object */
-  const optionsStore = isSvelteStore(options) ? options : readable(options)
-
-  /** Creates a store that has the default options applied */
-  const defaultedOptionsStore = derived(
-    [optionsStore, isRestoring],
-    ([$optionsStore, $isRestoring]) => {
-      const defaultedOptions = client.defaultQueryOptions($optionsStore)
-      defaultedOptions._optimisticResults = $isRestoring
-        ? 'isRestoring'
-        : 'optimistic'
-      return defaultedOptions
-    },
-  )
-
-  /** Creates the observer */
-  const observer = new Observer<
-    TQueryFnData,
-    TError,
-    TData,
-    TQueryData,
-    TQueryKey
-  >(client, get(defaultedOptionsStore))
-
-  defaultedOptionsStore.subscribe(($defaultedOptions) => {
-    observer.setOptions($defaultedOptions)
-  })
-
-  const result = derived<
-    typeof isRestoring,
-    QueryObserverResult<TData, TError>
-  >(isRestoring, ($isRestoring, set) => {
-    const unsubscribe = $isRestoring
-      ? noop
-      : observer.subscribe(notifyManager.batchCalls(set))
-    observer.updateResult()
-    return unsubscribe
-  })
-
-  /** Subscribe to changes in result and defaultedOptionsStore */
-  const { subscribe } = derived(
-    [result, defaultedOptionsStore],
-    ([$result, $defaultedOptionsStore]) => {
-      $result = observer.getOptimisticResult($defaultedOptionsStore)
-      return !$defaultedOptionsStore.notifyOnChangeProps
-        ? observer.trackResult($result)
-        : $result
-    },
-  )
-
-  return { subscribe }
-}
diff --git a/packages/svelte-query/src/createInfiniteQuery.ts b/packages/svelte-query/src/createInfiniteQuery.ts
index 7137800298..0e106c6e71 100644
--- a/packages/svelte-query/src/createInfiniteQuery.ts
+++ b/packages/svelte-query/src/createInfiniteQuery.ts
@@ -1,5 +1,5 @@
 import { InfiniteQueryObserver } from '@tanstack/query-core'
-import { createBaseQuery } from './createBaseQuery.js'
+import { createBaseQuery } from './createBaseQuery.svelte.js'
 import type {
   DefaultError,
   InfiniteData,
@@ -8,9 +8,9 @@ import type {
   QueryObserver,
 } from '@tanstack/query-core'
 import type {
+  Accessor,
   CreateInfiniteQueryOptions,
   CreateInfiniteQueryResult,
-  StoreOrVal,
 } from './types.js'
 
 export function createInfiniteQuery<
@@ -20,7 +20,7 @@ export function createInfiniteQuery<
   TQueryKey extends QueryKey = QueryKey,
   TPageParam = unknown,
 >(
-  options: StoreOrVal<
+  options: Accessor<
     CreateInfiniteQueryOptions<
       TQueryFnData,
       TError,
@@ -30,7 +30,7 @@ export function createInfiniteQuery<
       TPageParam
     >
   >,
-  queryClient?: QueryClient,
+  queryClient?: Accessor<QueryClient>,
 ): CreateInfiniteQueryResult<TData, TError> {
   return createBaseQuery(
     options,
diff --git a/packages/svelte-query/src/createMutation.svelte.ts b/packages/svelte-query/src/createMutation.svelte.ts
new file mode 100644
index 0000000000..62e39d98e6
--- /dev/null
+++ b/packages/svelte-query/src/createMutation.svelte.ts
@@ -0,0 +1,73 @@
+import { onDestroy } from 'svelte'
+
+import { MutationObserver, notifyManager } from '@tanstack/query-core'
+import { useQueryClient } from './useQueryClient.js'
+import type {
+  Accessor,
+  CreateMutateFunction,
+  CreateMutationOptions,
+  CreateMutationResult,
+} from './types.js'
+
+import type { DefaultError, QueryClient } from '@tanstack/query-core'
+
+/**
+ * @param options - A function that returns mutation options
+ * @param queryClient - Custom query client which overrides provider
+ */
+export function createMutation<
+  TData = unknown,
+  TError = DefaultError,
+  TVariables = void,
+  TContext = unknown,
+>(
+  options: Accessor<CreateMutationOptions<TData, TError, TVariables, TContext>>,
+  queryClient?: Accessor<QueryClient>,
+): CreateMutationResult<TData, TError, TVariables, TContext> {
+  const client = useQueryClient(queryClient?.())
+
+  const observer = $derived(
+    new MutationObserver<TData, TError, TVariables, TContext>(
+      client,
+      options(),
+    ),
+  )
+
+  const mutate = $state<
+    CreateMutateFunction<TData, TError, TVariables, TContext>
+  >((variables, mutateOptions) => {
+    observer.mutate(variables, mutateOptions).catch(noop)
+  })
+
+  $effect.pre(() => {
+    observer.setOptions(options())
+  })
+
+  const result = $state(observer.getCurrentResult())
+
+  const unsubscribe = observer.subscribe((val) => {
+    notifyManager.batchCalls(() => {
+      Object.assign(result, val)
+    })()
+  })
+
+  onDestroy(() => {
+    unsubscribe()
+  })
+
+  // @ts-expect-error
+  return new Proxy(result, {
+    get: (_, prop) => {
+      const r = {
+        ...result,
+        mutate,
+        mutateAsync: result.mutate,
+      }
+      if (prop == 'value') return r
+      // @ts-expect-error
+      return r[prop]
+    },
+  })
+}
+
+function noop() {}
diff --git a/packages/svelte-query/src/createMutation.ts b/packages/svelte-query/src/createMutation.ts
deleted file mode 100644
index 96198c3c1f..0000000000
--- a/packages/svelte-query/src/createMutation.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { derived, get, readable } from 'svelte/store'
-import { MutationObserver, notifyManager } from '@tanstack/query-core'
-import { useQueryClient } from './useQueryClient.js'
-import { isSvelteStore, noop } from './utils.js'
-import type {
-  CreateMutateFunction,
-  CreateMutationOptions,
-  CreateMutationResult,
-  StoreOrVal,
-} from './types.js'
-import type { DefaultError, QueryClient } from '@tanstack/query-core'
-
-export function createMutation<
-  TData = unknown,
-  TError = DefaultError,
-  TVariables = void,
-  TContext = unknown,
->(
-  options: StoreOrVal<
-    CreateMutationOptions<TData, TError, TVariables, TContext>
-  >,
-  queryClient?: QueryClient,
-): CreateMutationResult<TData, TError, TVariables, TContext> {
-  const client = useQueryClient(queryClient)
-
-  const optionsStore = isSvelteStore(options) ? options : readable(options)
-
-  const observer = new MutationObserver<TData, TError, TVariables, TContext>(
-    client,
-    get(optionsStore),
-  )
-  let mutate: CreateMutateFunction<TData, TError, TVariables, TContext>
-
-  optionsStore.subscribe(($options) => {
-    mutate = (variables, mutateOptions) => {
-      observer.mutate(variables, mutateOptions).catch(noop)
-    }
-    observer.setOptions($options)
-  })
-
-  const result = readable(observer.getCurrentResult(), (set) => {
-    return observer.subscribe(notifyManager.batchCalls((val) => set(val)))
-  })
-
-  const { subscribe } = derived(result, ($result) => ({
-    ...$result,
-    mutate,
-    mutateAsync: $result.mutate,
-  }))
-
-  return { subscribe }
-}
diff --git a/packages/svelte-query/src/createQueries.ts b/packages/svelte-query/src/createQueries.svelte.ts
similarity index 59%
rename from packages/svelte-query/src/createQueries.ts
rename to packages/svelte-query/src/createQueries.svelte.ts
index 53877565b1..e546dc600d 100644
--- a/packages/svelte-query/src/createQueries.ts
+++ b/packages/svelte-query/src/createQueries.svelte.ts
@@ -1,33 +1,34 @@
-import { QueriesObserver, notifyManager } from '@tanstack/query-core'
-import { derived, get, readable } from 'svelte/store'
+import { QueriesObserver } from '@tanstack/query-core'
+import { untrack } from 'svelte'
 import { useIsRestoring } from './useIsRestoring.js'
+import { createRawRef } from './containers.svelte.js'
 import { useQueryClient } from './useQueryClient.js'
-import { isSvelteStore, noop } from './utils.js'
-import type { Readable } from 'svelte/store'
-import type { StoreOrVal } from './types.js'
+import type {
+  Accessor,
+  CreateQueryOptions,
+  CreateQueryResult,
+  DefinedCreateQueryResult,
+} from './types.js'
 import type {
   DefaultError,
-  DefinedQueryObserverResult,
   OmitKeyof,
   QueriesObserverOptions,
   QueriesPlaceholderDataFunction,
   QueryClient,
   QueryFunction,
   QueryKey,
-  QueryObserverOptions,
-  QueryObserverResult,
   ThrowOnError,
 } from '@tanstack/query-core'
 
 // This defines the `CreateQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.
 // `placeholderData` function always gets undefined passed
-type QueryObserverOptionsForCreateQueries<
+type CreateQueryOptionsForCreateQueries<
   TQueryFnData = unknown,
   TError = DefaultError,
   TData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey,
 > = OmitKeyof<
-  QueryObserverOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,
+  CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
   'placeholderData'
 > & {
   placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction<TQueryFnData>
@@ -37,60 +38,60 @@ type QueryObserverOptionsForCreateQueries<
 type MAXIMUM_DEPTH = 20
 
 // Widen the type of the symbol to enable type inference even if skipToken is not immutable.
-type SkipTokenForUseQueries = symbol
+type SkipTokenForCreateQueries = symbol
 
-type GetQueryObserverOptionsForCreateQueries<T> =
+type GetCreateQueryOptionsForCreateQueries<T> =
   // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }
   T extends {
     queryFnData: infer TQueryFnData
     error?: infer TError
     data: infer TData
   }
-    ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData>
+    ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError, TData>
     : T extends { queryFnData: infer TQueryFnData; error?: infer TError }
-      ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError>
+      ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError>
       : T extends { data: infer TData; error?: infer TError }
-        ? QueryObserverOptionsForCreateQueries<unknown, TError, TData>
+        ? CreateQueryOptionsForCreateQueries<unknown, TError, TData>
         : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]
           T extends [infer TQueryFnData, infer TError, infer TData]
-          ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError, TData>
+          ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError, TData>
           : T extends [infer TQueryFnData, infer TError]
-            ? QueryObserverOptionsForCreateQueries<TQueryFnData, TError>
+            ? CreateQueryOptionsForCreateQueries<TQueryFnData, TError>
             : T extends [infer TQueryFnData]
-              ? QueryObserverOptionsForCreateQueries<TQueryFnData>
+              ? CreateQueryOptionsForCreateQueries<TQueryFnData>
               : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided
                 T extends {
                     queryFn?:
                       | QueryFunction<infer TQueryFnData, infer TQueryKey>
-                      | SkipTokenForUseQueries
+                      | SkipTokenForCreateQueries
                     select?: (data: any) => infer TData
                     throwOnError?: ThrowOnError<any, infer TError, any, any>
                   }
-                ? QueryObserverOptionsForCreateQueries<
+                ? CreateQueryOptionsForCreateQueries<
                     TQueryFnData,
                     unknown extends TError ? DefaultError : TError,
                     unknown extends TData ? TQueryFnData : TData,
                     TQueryKey
                   >
                 : // Fallback
-                  QueryObserverOptionsForCreateQueries
+                  CreateQueryOptionsForCreateQueries
 
-// A defined initialData setting should return a DefinedQueryObserverResult rather than CreateQueryResult
+// A defined initialData setting should return a DefinedCreateQueryResult rather than CreateQueryResult
 type GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {
   initialData?: infer TInitialData
 }
   ? unknown extends TInitialData
-    ? QueryObserverResult<TData, TError>
+    ? CreateQueryResult<TData, TError>
     : TInitialData extends TData
-      ? DefinedQueryObserverResult<TData, TError>
+      ? DefinedCreateQueryResult<TData, TError>
       : TInitialData extends () => infer TInitialDataResult
         ? unknown extends TInitialDataResult
-          ? QueryObserverResult<TData, TError>
+          ? CreateQueryResult<TData, TError>
           : TInitialDataResult extends TData
-            ? DefinedQueryObserverResult<TData, TError>
-            : QueryObserverResult<TData, TError>
-        : QueryObserverResult<TData, TError>
-  : QueryObserverResult<TData, TError>
+            ? DefinedCreateQueryResult<TData, TError>
+            : CreateQueryResult<TData, TError>
+        : CreateQueryResult<TData, TError>
+  : CreateQueryResult<TData, TError>
 
 type GetCreateQueryResult<T> =
   // Part 1: responsible for mapping explicit type parameter to function result, if object
@@ -111,7 +112,7 @@ type GetCreateQueryResult<T> =
                 T extends {
                     queryFn?:
                       | QueryFunction<infer TQueryFnData, any>
-                      | SkipTokenForUseQueries
+                      | SkipTokenForCreateQueries
                     select?: (data: any) => infer TData
                     throwOnError?: ThrowOnError<any, infer TError, any, any>
                   }
@@ -121,7 +122,7 @@ type GetCreateQueryResult<T> =
                     unknown extends TError ? DefaultError : TError
                   >
                 : // Fallback
-                  QueryObserverResult
+                  CreateQueryResult
 
 /**
  * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param
@@ -131,15 +132,15 @@ export type QueriesOptions<
   TResults extends Array<any> = [],
   TDepth extends ReadonlyArray<number> = [],
 > = TDepth['length'] extends MAXIMUM_DEPTH
-  ? Array<QueryObserverOptionsForCreateQueries>
+  ? Array<CreateQueryOptionsForCreateQueries>
   : T extends []
     ? []
     : T extends [infer Head]
-      ? [...TResults, GetQueryObserverOptionsForCreateQueries<Head>]
+      ? [...TResults, GetCreateQueryOptionsForCreateQueries<Head>]
       : T extends [infer Head, ...infer Tails]
         ? QueriesOptions<
             [...Tails],
-            [...TResults, GetQueryObserverOptionsForCreateQueries<Head>],
+            [...TResults, GetCreateQueryOptionsForCreateQueries<Head>],
             [...TDepth, 1]
           >
         : ReadonlyArray<unknown> extends T
@@ -147,7 +148,7 @@ export type QueriesOptions<
           : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!
             // use this to infer the param types in the case of Array.map() argument
             T extends Array<
-                QueryObserverOptionsForCreateQueries<
+                CreateQueryOptionsForCreateQueries<
                   infer TQueryFnData,
                   infer TError,
                   infer TData,
@@ -155,7 +156,7 @@ export type QueriesOptions<
                 >
               >
             ? Array<
-                QueryObserverOptionsForCreateQueries<
+                CreateQueryOptionsForCreateQueries<
                   TQueryFnData,
                   TError,
                   TData,
@@ -163,7 +164,7 @@ export type QueriesOptions<
                 >
               >
             : // Fallback
-              Array<QueryObserverOptionsForCreateQueries>
+              Array<CreateQueryOptionsForCreateQueries>
 
 /**
  * QueriesResults reducer recursively maps type param to results
@@ -173,7 +174,7 @@ export type QueriesResults<
   TResults extends Array<any> = [],
   TDepth extends ReadonlyArray<number> = [],
 > = TDepth['length'] extends MAXIMUM_DEPTH
-  ? Array<QueryObserverResult>
+  ? Array<CreateQueryResult>
   : T extends []
     ? []
     : T extends [infer Head]
@@ -190,75 +191,64 @@ export function createQueries<
   T extends Array<any>,
   TCombinedResult = QueriesResults<T>,
 >(
-  {
-    queries,
-    ...options
-  }: {
+  createQueriesOptions: Accessor<{
     queries:
-      | StoreOrVal<[...QueriesOptions<T>]>
-      | StoreOrVal<
-          [...{ [K in keyof T]: GetQueryObserverOptionsForCreateQueries<T[K]> }]
-        >
+      | readonly [...QueriesOptions<T>]
+      | readonly [
+          ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries<T[K]> },
+        ]
     combine?: (result: QueriesResults<T>) => TCombinedResult
-  },
-  queryClient?: QueryClient,
-): Readable<TCombinedResult> {
-  const client = useQueryClient(queryClient)
+  }>,
+  queryClient?: Accessor<QueryClient>,
+): TCombinedResult {
+  const client = $derived(useQueryClient(queryClient?.()))
   const isRestoring = useIsRestoring()
 
-  const queriesStore = isSvelteStore(queries) ? queries : readable(queries)
-
-  const defaultedQueriesStore = derived(
-    [queriesStore, isRestoring],
-    ([$queries, $isRestoring]) => {
-      return $queries.map((opts) => {
-        const defaultedOptions = client.defaultQueryOptions(
-          opts as QueryObserverOptions,
-        )
-        // Make sure the results are already in fetching state before subscribing or updating options
-        defaultedOptions._optimisticResults = $isRestoring
-          ? 'isRestoring'
-          : 'optimistic'
-        return defaultedOptions
-      })
-    },
+  const { queries, combine } = $derived.by(createQueriesOptions)
+  const resolvedQueryOptions = $derived(
+    queries.map((opts) => {
+      const resolvedOptions = client.defaultQueryOptions(opts)
+      // Make sure the results are already in fetching state before subscribing or updating options
+      resolvedOptions._optimisticResults = isRestoring.current
+        ? 'isRestoring'
+        : 'optimistic'
+      return resolvedOptions
+    }),
   )
-  const observer = new QueriesObserver<TCombinedResult>(
-    client,
-    get(defaultedQueriesStore),
-    options as QueriesObserverOptions<TCombinedResult>,
+
+  const observer = $derived(
+    new QueriesObserver<TCombinedResult>(
+      client,
+      untrack(() => resolvedQueryOptions),
+      untrack(() => combine as QueriesObserverOptions<TCombinedResult>),
+    ),
   )
 
-  defaultedQueriesStore.subscribe(($defaultedQueries) => {
-    // Do not notify on updates because of changes in the options because
-    // these changes should already be reflected in the optimistic result.
-    observer.setQueries(
-      $defaultedQueries,
-      options as QueriesObserverOptions<TCombinedResult>,
+  function createResult() {
+    const [_, getCombinedResult, trackResult] = observer.getOptimisticResult(
+      resolvedQueryOptions,
+      combine as QueriesObserverOptions<TCombinedResult>['combine'],
     )
-  })
+    return getCombinedResult(trackResult())
+  }
 
-  const result = derived([isRestoring], ([$isRestoring], set) => {
-    const unsubscribe = $isRestoring
-      ? noop
-      : observer.subscribe(notifyManager.batchCalls(set))
+  // @ts-expect-error - the crazy-complex TCombinedResult type doesn't like being called an array
+  // svelte-ignore state_referenced_locally
+  const [results, update] = createRawRef<TCombinedResult>(createResult())
 
-    return () => unsubscribe()
+  $effect(() => {
+    const unsubscribe = isRestoring.current
+      ? () => undefined
+      : observer.subscribe(() => update(createResult()))
+    return unsubscribe
   })
 
-  const { subscribe } = derived(
-    [result, defaultedQueriesStore],
-    // @ts-expect-error svelte-check thinks this is unused
-    ([$result, $defaultedQueriesStore]) => {
-      const [rawResult, combineResult, trackResult] =
-        observer.getOptimisticResult(
-          $defaultedQueriesStore,
-          (options as QueriesObserverOptions<TCombinedResult>).combine,
-        )
-      $result = rawResult
-      return combineResult(trackResult())
-    },
-  )
+  $effect.pre(() => {
+    observer.setQueries(resolvedQueryOptions, {
+      combine,
+    } as QueriesObserverOptions<TCombinedResult>)
+    update(createResult())
+  })
 
-  return { subscribe }
+  return results
 }
diff --git a/packages/svelte-query/src/createQuery.ts b/packages/svelte-query/src/createQuery.ts
index 51a43c274c..bf7efe81a7 100644
--- a/packages/svelte-query/src/createQuery.ts
+++ b/packages/svelte-query/src/createQuery.ts
@@ -1,11 +1,11 @@
 import { QueryObserver } from '@tanstack/query-core'
-import { createBaseQuery } from './createBaseQuery.js'
+import { createBaseQuery } from './createBaseQuery.svelte.js'
 import type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core'
 import type {
+  Accessor,
   CreateQueryOptions,
   CreateQueryResult,
   DefinedCreateQueryResult,
-  StoreOrVal,
 } from './types.js'
 import type {
   DefinedInitialDataOptions,
@@ -18,11 +18,11 @@ export function createQuery<
   TData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey,
 >(
-  options: StoreOrVal<
-    DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>
+  options: Accessor<
+    UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>
   >,
-  queryClient?: QueryClient,
-): DefinedCreateQueryResult<TData, TError>
+  queryClient?: Accessor<QueryClient>,
+): CreateQueryResult<TData, TError>
 
 export function createQuery<
   TQueryFnData = unknown,
@@ -30,27 +30,25 @@ export function createQuery<
   TData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey,
 >(
-  options: StoreOrVal<
-    UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>
+  options: Accessor<
+    DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>
   >,
-  queryClient?: QueryClient,
-): CreateQueryResult<TData, TError>
+  queryClient?: Accessor<QueryClient>,
+): DefinedCreateQueryResult<TData, TError>
 
 export function createQuery<
-  TQueryFnData = unknown,
+  TQueryFnData,
   TError = DefaultError,
   TData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey,
 >(
-  options: StoreOrVal<
-    CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>
-  >,
-  queryClient?: QueryClient,
+  options: Accessor<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>>,
+  queryClient?: Accessor<QueryClient>,
 ): CreateQueryResult<TData, TError>
 
 export function createQuery(
-  options: StoreOrVal<CreateQueryOptions>,
-  queryClient?: QueryClient,
+  options: Accessor<CreateQueryOptions>,
+  queryClient?: Accessor<QueryClient>,
 ) {
   return createBaseQuery(options, QueryObserver, queryClient)
 }
diff --git a/packages/svelte-query/src/index.ts b/packages/svelte-query/src/index.ts
index 735cd89f59..1b74a9be91 100644
--- a/packages/svelte-query/src/index.ts
+++ b/packages/svelte-query/src/index.ts
@@ -8,20 +8,20 @@ export * from './types.js'
 export * from './context.js'
 
 export { createQuery } from './createQuery.js'
-export type { QueriesResults, QueriesOptions } from './createQueries.js'
+export type { QueriesResults, QueriesOptions } from './createQueries.svelte.js'
 export type {
   DefinedInitialDataOptions,
   UndefinedInitialDataOptions,
 } from './queryOptions.js'
 export { queryOptions } from './queryOptions.js'
-export { createQueries } from './createQueries.js'
+export { createQueries } from './createQueries.svelte.js'
 export { createInfiniteQuery } from './createInfiniteQuery.js'
 export { infiniteQueryOptions } from './infiniteQueryOptions.js'
-export { createMutation } from './createMutation.js'
-export { useMutationState } from './useMutationState.js'
+export { createMutation } from './createMutation.svelte.js'
+export { useMutationState } from './useMutationState.svelte.js'
 export { useQueryClient } from './useQueryClient.js'
-export { useIsFetching } from './useIsFetching.js'
-export { useIsMutating } from './useIsMutating.js'
+export { useIsFetching } from './useIsFetching.svelte.js'
+export { useIsMutating } from './useIsMutating.svelte.js'
 export { useIsRestoring } from './useIsRestoring.js'
 export { useHydrate } from './useHydrate.js'
 export { default as HydrationBoundary } from './HydrationBoundary.svelte'
diff --git a/packages/svelte-query/src/types.ts b/packages/svelte-query/src/types.ts
index fb835c5e7b..1c6cc4d20e 100644
--- a/packages/svelte-query/src/types.ts
+++ b/packages/svelte-query/src/types.ts
@@ -1,3 +1,4 @@
+import type { Snippet } from 'svelte'
 import type {
   DefaultError,
   DefinedQueryObserverResult,
@@ -9,16 +10,14 @@ import type {
   MutationObserverOptions,
   MutationObserverResult,
   MutationState,
-  OmitKeyof,
   Override,
+  QueryClient,
   QueryKey,
   QueryObserverOptions,
   QueryObserverResult,
 } from '@tanstack/query-core'
-import type { Readable } from 'svelte/store'
 
-/** Allows a type to be either the base object or a store of that object */
-export type StoreOrVal<T> = T | Readable<T>
+export type Accessor<T> = () => T
 
 /** Options for createBaseQuery */
 export type CreateBaseQueryOptions<
@@ -33,7 +32,7 @@ export type CreateBaseQueryOptions<
 export type CreateBaseQueryResult<
   TData = unknown,
   TError = DefaultError,
-> = Readable<QueryObserverResult<TData, TError>>
+> = QueryObserverResult<TData, TError>
 
 /** Options for createQuery */
 export type CreateQueryOptions<
@@ -70,13 +69,13 @@ export type CreateInfiniteQueryOptions<
 export type CreateInfiniteQueryResult<
   TData = unknown,
   TError = DefaultError,
-> = Readable<InfiniteQueryObserverResult<TData, TError>>
+> = InfiniteQueryObserverResult<TData, TError>
 
 /** Options for createBaseQuery with initialData */
 export type DefinedCreateBaseQueryResult<
   TData = unknown,
   TError = DefaultError,
-> = Readable<DefinedQueryObserverResult<TData, TError>>
+> = DefinedQueryObserverResult<TData, TError>
 
 /** Options for createQuery with initialData */
 export type DefinedCreateQueryResult<
@@ -90,9 +89,9 @@ export type CreateMutationOptions<
   TError = DefaultError,
   TVariables = void,
   TContext = unknown,
-> = OmitKeyof<
+> = Omit<
   MutationObserverOptions<TData, TError, TVariables, TContext>,
-  '_defaulted'
+  '_defaulted' | 'variables'
 >
 
 export type CreateMutateFunction<
@@ -129,7 +128,7 @@ export type CreateMutationResult<
   TError = DefaultError,
   TVariables = unknown,
   TContext = unknown,
-> = Readable<CreateBaseMutationResult<TData, TError, TVariables, TContext>>
+> = CreateBaseMutationResult<TData, TError, TVariables, TContext>
 
 /** Options for useMutationState */
 export type MutationStateOptions<TResult = MutationState> = {
@@ -138,3 +137,8 @@ export type MutationStateOptions<TResult = MutationState> = {
     mutation: Mutation<unknown, DefaultError, unknown, unknown>,
   ) => TResult
 }
+
+export type QueryClientProviderProps = {
+  client: QueryClient
+  children: Snippet
+}
diff --git a/packages/svelte-query/src/useIsFetching.svelte.ts b/packages/svelte-query/src/useIsFetching.svelte.ts
new file mode 100644
index 0000000000..0b8c47e3fd
--- /dev/null
+++ b/packages/svelte-query/src/useIsFetching.svelte.ts
@@ -0,0 +1,16 @@
+import { ReactiveValue } from './containers.svelte.js'
+import { useQueryClient } from './useQueryClient.js'
+import type { QueryClient, QueryFilters } from '@tanstack/query-core'
+
+export function useIsFetching(
+  filters?: QueryFilters,
+  queryClient?: QueryClient,
+): ReactiveValue<number> {
+  const client = useQueryClient(queryClient)
+  const queryCache = client.getQueryCache()
+
+  return new ReactiveValue(
+    () => client.isFetching(filters),
+    (update) => queryCache.subscribe(update),
+  )
+}
diff --git a/packages/svelte-query/src/useIsFetching.ts b/packages/svelte-query/src/useIsFetching.ts
deleted file mode 100644
index e784896192..0000000000
--- a/packages/svelte-query/src/useIsFetching.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { notifyManager } from '@tanstack/query-core'
-import { readable } from 'svelte/store'
-import { useQueryClient } from './useQueryClient.js'
-import type { Readable } from 'svelte/store'
-import type { QueryClient, QueryFilters } from '@tanstack/query-core'
-
-export function useIsFetching(
-  filters?: QueryFilters,
-  queryClient?: QueryClient,
-): Readable<number> {
-  const client = useQueryClient(queryClient)
-  const cache = client.getQueryCache()
-  // isFetching is the prev value initialized on mount *
-  let isFetching = client.isFetching(filters)
-
-  const { subscribe } = readable(isFetching, (set) => {
-    return cache.subscribe(
-      notifyManager.batchCalls(() => {
-        const newIsFetching = client.isFetching(filters)
-        if (isFetching !== newIsFetching) {
-          // * and update with each change
-          isFetching = newIsFetching
-          set(isFetching)
-        }
-      }),
-    )
-  })
-
-  return { subscribe }
-}
diff --git a/packages/svelte-query/src/useIsMutating.svelte.ts b/packages/svelte-query/src/useIsMutating.svelte.ts
new file mode 100644
index 0000000000..21ac56e7a8
--- /dev/null
+++ b/packages/svelte-query/src/useIsMutating.svelte.ts
@@ -0,0 +1,16 @@
+import { useQueryClient } from './useQueryClient.js'
+import { ReactiveValue } from './containers.svelte.js'
+import type { MutationFilters, QueryClient } from '@tanstack/query-core'
+
+export function useIsMutating(
+  filters?: MutationFilters,
+  queryClient?: QueryClient,
+): ReactiveValue<number> {
+  const client = useQueryClient(queryClient)
+  const cache = client.getMutationCache()
+
+  return new ReactiveValue(
+    () => client.isMutating(filters),
+    (update) => cache.subscribe(update),
+  )
+}
diff --git a/packages/svelte-query/src/useIsMutating.ts b/packages/svelte-query/src/useIsMutating.ts
deleted file mode 100644
index 258e8fe98c..0000000000
--- a/packages/svelte-query/src/useIsMutating.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { notifyManager } from '@tanstack/query-core'
-import { readable } from 'svelte/store'
-import { useQueryClient } from './useQueryClient.js'
-import type { Readable } from 'svelte/store'
-import type { MutationFilters, QueryClient } from '@tanstack/query-core'
-
-export function useIsMutating(
-  filters?: MutationFilters,
-  queryClient?: QueryClient,
-): Readable<number> {
-  const client = useQueryClient(queryClient)
-  const cache = client.getMutationCache()
-  // isMutating is the prev value initialized on mount *
-  let isMutating = client.isMutating(filters)
-
-  const { subscribe } = readable(isMutating, (set) => {
-    return cache.subscribe(
-      notifyManager.batchCalls(() => {
-        const newIisMutating = client.isMutating(filters)
-        if (isMutating !== newIisMutating) {
-          // * and update with each change
-          isMutating = newIisMutating
-          set(isMutating)
-        }
-      }),
-    )
-  })
-
-  return { subscribe }
-}
diff --git a/packages/svelte-query/src/useIsRestoring.ts b/packages/svelte-query/src/useIsRestoring.ts
index c22d8af402..99dd4ddacb 100644
--- a/packages/svelte-query/src/useIsRestoring.ts
+++ b/packages/svelte-query/src/useIsRestoring.ts
@@ -1,6 +1,6 @@
 import { getIsRestoringContext } from './context.js'
-import type { Readable } from 'svelte/store'
+import type { Box } from './containers.svelte.js'
 
-export function useIsRestoring(): Readable<boolean> {
+export function useIsRestoring(): Box<boolean> {
   return getIsRestoringContext()
 }
diff --git a/packages/svelte-query/src/useMutationState.svelte.ts b/packages/svelte-query/src/useMutationState.svelte.ts
new file mode 100644
index 0000000000..c517e64b48
--- /dev/null
+++ b/packages/svelte-query/src/useMutationState.svelte.ts
@@ -0,0 +1,56 @@
+import { replaceEqualDeep } from '@tanstack/query-core'
+import { useQueryClient } from './useQueryClient.js'
+import type {
+  MutationCache,
+  MutationState,
+  QueryClient,
+} from '@tanstack/query-core'
+import type { MutationStateOptions } from './types.js'
+
+function getResult<TResult = MutationState>(
+  mutationCache: MutationCache,
+  options: MutationStateOptions<TResult>,
+): Array<TResult> {
+  return mutationCache
+    .findAll(options.filters)
+    .map(
+      (mutation): TResult =>
+        (options.select ? options.select(mutation) : mutation.state) as TResult,
+    )
+}
+
+export function useMutationState<TResult = MutationState>(
+  options: MutationStateOptions<TResult> = {},
+  queryClient?: QueryClient,
+): Array<TResult> {
+  const mutationCache = useQueryClient(queryClient).getMutationCache()
+  const result = $state(getResult(mutationCache, options))
+
+  $effect(() => {
+    const unsubscribe = mutationCache.subscribe(() => {
+      const nextResult = replaceEqualDeep(
+        result,
+        getResult(mutationCache, options),
+      )
+      if (result !== nextResult) {
+        Object.assign(result, nextResult)
+      }
+    })
+
+    return unsubscribe
+  })
+
+  /*  $effect(() => {
+    mutationCache.subscribe(() => {
+      const nextResult = replaceEqualDeep(
+        result.current,
+        getResult(mutationCache, optionsRef),
+      )
+      if (result.current !== nextResult) {
+        result = nextResult
+        //notifyManager.schedule(onStoreChange)
+      }
+    })
+  }) */
+  return result
+}
diff --git a/packages/svelte-query/src/useMutationState.ts b/packages/svelte-query/src/useMutationState.ts
deleted file mode 100644
index 0367eee5db..0000000000
--- a/packages/svelte-query/src/useMutationState.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { readable } from 'svelte/store'
-import { notifyManager, replaceEqualDeep } from '@tanstack/query-core'
-import { useQueryClient } from './useQueryClient.js'
-import type {
-  MutationCache,
-  MutationState,
-  QueryClient,
-} from '@tanstack/query-core'
-import type { Readable } from 'svelte/store'
-import type { MutationStateOptions } from './types.js'
-
-function getResult<TResult = MutationState>(
-  mutationCache: MutationCache,
-  options: MutationStateOptions<TResult>,
-): Array<TResult> {
-  return mutationCache
-    .findAll(options.filters)
-    .map(
-      (mutation): TResult =>
-        (options.select ? options.select(mutation) : mutation.state) as TResult,
-    )
-}
-
-export function useMutationState<TResult = MutationState>(
-  options: MutationStateOptions<TResult> = {},
-  queryClient?: QueryClient,
-): Readable<Array<TResult>> {
-  const client = useQueryClient(queryClient)
-  const mutationCache = client.getMutationCache()
-
-  let result = getResult(mutationCache, options)
-
-  const { subscribe } = readable(result, (set) => {
-    return mutationCache.subscribe(
-      notifyManager.batchCalls(() => {
-        const nextResult = replaceEqualDeep(
-          result,
-          getResult(mutationCache, options),
-        )
-        if (result !== nextResult) {
-          result = nextResult
-          set(result)
-        }
-      }),
-    )
-  })
-
-  return { subscribe }
-}
diff --git a/packages/svelte-query/src/utils.ts b/packages/svelte-query/src/utils.ts
deleted file mode 100644
index 29dd68b659..0000000000
--- a/packages/svelte-query/src/utils.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { Readable } from 'svelte/store'
-import type { StoreOrVal } from './types.js'
-
-export function isSvelteStore<T extends object>(
-  obj: StoreOrVal<T>,
-): obj is Readable<T> {
-  return 'subscribe' in obj && typeof obj.subscribe === 'function'
-}
-
-export function noop(): void {}
diff --git a/packages/svelte-query/tests/QueryClientProvider/ChildComponent.svelte b/packages/svelte-query/tests/QueryClientProvider/ChildComponent.svelte
index 3c5414b059..8bf3bc199e 100644
--- a/packages/svelte-query/tests/QueryClientProvider/ChildComponent.svelte
+++ b/packages/svelte-query/tests/QueryClientProvider/ChildComponent.svelte
@@ -2,13 +2,13 @@
   import { createQuery } from '../../src/index.js'
   import { sleep } from '@tanstack/query-test-utils'
 
-  const query = createQuery({
+  const query = createQuery(() => ({
     queryKey: ['hello'],
     queryFn: async () => {
       await sleep(5)
       return 'test'
     },
-  })
+  }))
 </script>
 
-<div>Data: {$query.data ?? 'undefined'}</div>
+<div>Data: {query.data ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/QueryClientProvider/ParentComponent.svelte b/packages/svelte-query/tests/QueryClientProvider/ParentComponent.svelte
index dc2440ef94..c7b6fa0c5b 100644
--- a/packages/svelte-query/tests/QueryClientProvider/ParentComponent.svelte
+++ b/packages/svelte-query/tests/QueryClientProvider/ParentComponent.svelte
@@ -1,12 +1,9 @@
 <script lang="ts">
-  import { QueryClient } from '@tanstack/query-core'
   import { QueryClientProvider } from '../../src/index.js'
   import ChildComponent from './ChildComponent.svelte'
-  import type { QueryCache } from '@tanstack/query-core'
+  import type { QueryClient } from '@tanstack/query-core'
 
-  export let queryCache: QueryCache
-
-  const queryClient = new QueryClient({ queryCache })
+  let { queryClient }: { queryClient: QueryClient } = $props()
 </script>
 
 <QueryClientProvider client={queryClient}>
diff --git a/packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.test.ts b/packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.svelte.test.ts
similarity index 73%
rename from packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.test.ts
rename to packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.svelte.test.ts
index f144e1c9f9..0a69bc6e1f 100644
--- a/packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.test.ts
+++ b/packages/svelte-query/tests/QueryClientProvider/QueryClientProvider.svelte.test.ts
@@ -1,15 +1,16 @@
 import { describe, expect, test } from 'vitest'
 import { render, waitFor } from '@testing-library/svelte'
-import { QueryCache } from '@tanstack/query-core'
+import { QueryClient } from '@tanstack/query-core'
 import ParentComponent from './ParentComponent.svelte'
 
 describe('QueryClientProvider', () => {
   test('Sets a specific cache for all queries to use', async () => {
-    const queryCache = new QueryCache()
+    const queryClient = new QueryClient()
+    const queryCache = queryClient.getQueryCache()
 
     const rendered = render(ParentComponent, {
       props: {
-        queryCache: queryCache,
+        queryClient: queryClient,
       },
     })
 
diff --git a/packages/svelte-query/tests/containers.svelte.test.ts b/packages/svelte-query/tests/containers.svelte.test.ts
new file mode 100644
index 0000000000..3511dbb5b5
--- /dev/null
+++ b/packages/svelte-query/tests/containers.svelte.test.ts
@@ -0,0 +1,219 @@
+import { flushSync } from 'svelte'
+import { describe, expect, it } from 'vitest'
+import { createRawRef } from '../src/containers.svelte.js'
+import { withEffectRoot } from './utils.svelte.js'
+
+describe('createRawRef', () => {
+  it('should create a reactive reference', () => {
+    const [ref, update] = createRawRef({ a: 1, b: 2 })
+
+    expect(ref).toEqual({ a: 1, b: 2 })
+
+    update({ a: 3, b: 4 })
+    expect(ref).toEqual({ a: 3, b: 4 })
+
+    ref.a = 5
+    expect(ref).toEqual({ a: 5, b: 4 })
+  })
+
+  it('should handle nested objects', () => {
+    const [ref, update] = createRawRef<{ a: any }>({ a: { b: { c: 1 } } })
+
+    expect(ref).toEqual({ a: { b: { c: 1 } } })
+
+    // update with same structure
+    update({ a: { b: { c: 2 } } })
+    expect(ref).toEqual({ a: { b: { c: 2 } } })
+
+    ref.a.b.c = 3
+    expect(ref).toEqual({ a: { b: { c: 3 } } })
+
+    // update with different structure should wipe out everything below the first level
+    update({ a: { b: 3 } })
+    expect(ref).toEqual({ a: { b: 3 } })
+  })
+
+  it('should remove properties when a new object is assigned', () => {
+    const [ref, update] = createRawRef<Record<string, number>>({
+      a: 1,
+      b: 2,
+    })
+
+    expect(ref).toEqual({ a: 1, b: 2 })
+
+    update({ a: 3 })
+    expect(ref).toEqual({ a: 3 })
+  })
+
+  it(
+    'should not break reactivity when removing keys',
+    withEffectRoot(() => {
+      const [ref, update] = createRawRef<Record<string, number>>({ a: 1, b: 2 })
+      const states: Array<number | undefined> = []
+      $effect(() => {
+        states.push(ref.b)
+      })
+
+      // these flushSync calls force the effect to run and push the value to the states array
+      flushSync()
+      update({ a: 3 }) // should remove b, and should rerun the effect
+      flushSync()
+      update({ a: 3, b: 4 }) // should add b back, and should rerun the effect
+      flushSync()
+      delete ref.b // should remove b, and should rerun the effect
+      flushSync()
+      delete ref.a // should remove a, and should _not_ rerun the effect
+      expect(states).toEqual([2, undefined, 4, undefined])
+    }),
+  )
+
+  it(
+    'should correctly trap calls to `in`',
+    withEffectRoot(() => {
+      const [ref, update] = createRawRef<Record<string, number>>({
+        a: 1,
+        b: 2,
+      })
+
+      expect('b' in ref).toBe(true)
+      delete ref.b
+      expect('b' in ref).toBe(false)
+      update({})
+      expect('a' in ref).toBe(false)
+      update({ a: 1, b: 2 })
+      expect('b' in ref).toBe(true)
+      expect('a' in ref).toBe(true)
+    }),
+  )
+
+  it('should correctly trap calls to `ownKeys`', () => {
+    const [ref, update] = createRawRef<Record<string, number>>({
+      a: 1,
+      b: 2,
+    })
+
+    expect(Object.keys(ref)).toEqual(['a', 'b'])
+
+    delete ref.b
+    expect(Reflect.ownKeys(ref)).toEqual(['a'])
+
+    update({})
+    expect(Object.keys(ref)).toEqual([])
+
+    update({ a: 1, b: 2 })
+    expect(Object.keys(ref)).toEqual(['a', 'b'])
+  })
+
+  it('should correctly trap calls to `getOwnPropertyDescriptor`', () => {
+    const [ref, update] = createRawRef<Record<string, number>>({
+      a: 1,
+      b: 2,
+    })
+
+    expect(Reflect.getOwnPropertyDescriptor(ref, 'b')).toEqual({
+      configurable: true,
+      enumerable: true,
+      get: expect.any(Function),
+      set: expect.any(Function),
+    })
+
+    delete ref.b
+    expect(Reflect.getOwnPropertyDescriptor(ref, 'b')).toEqual(undefined)
+
+    update({})
+    expect(Reflect.getOwnPropertyDescriptor(ref, 'a')).toEqual(undefined)
+
+    update({ a: 1, b: 2 })
+    expect(Reflect.getOwnPropertyDescriptor(ref, 'a')).toEqual({
+      configurable: true,
+      enumerable: true,
+      get: expect.any(Function),
+      set: expect.any(Function),
+    })
+    expect(Reflect.getOwnPropertyDescriptor(ref, 'b')).toEqual({
+      configurable: true,
+      enumerable: true,
+      get: expect.any(Function),
+      set: expect.any(Function),
+    })
+  })
+
+  it('should lazily access values when using `update`', () => {
+    let aAccessed = false
+    let bAccessed = false
+    const [ref, update] = createRawRef({
+      get a() {
+        aAccessed = true
+        return 1
+      },
+      get b() {
+        bAccessed = true
+        return 2
+      },
+    })
+
+    expect(aAccessed).toBe(false)
+    expect(bAccessed).toBe(false)
+
+    expect(ref.a).toBe(1)
+
+    expect(aAccessed).toBe(true)
+    expect(bAccessed).toBe(false)
+
+    aAccessed = false
+    bAccessed = false
+
+    update({
+      get a() {
+        aAccessed = true
+        return 2
+      },
+      get b() {
+        bAccessed = true
+        return 3
+      },
+    })
+
+    expect(aAccessed).toBe(false)
+    expect(bAccessed).toBe(false)
+
+    expect(ref.a).toBe(2)
+
+    expect(aAccessed).toBe(true)
+    expect(bAccessed).toBe(false)
+  })
+
+  it('should handle arrays', () => {
+    const [ref, update] = createRawRef([1, 2, 3])
+
+    expect(ref).toEqual([1, 2, 3])
+
+    ref[0] = 4
+    expect(ref).toEqual([4, 2, 3])
+
+    update([5, 6])
+    expect(ref).toEqual([5, 6])
+
+    update([7, 8, 9])
+    expect(ref).toEqual([7, 8, 9])
+  })
+
+  it('should behave like a regular object when not using `update`', () => {
+    const [ref] = createRawRef<Record<string, unknown>>({ a: 1, b: 2 })
+
+    expect(ref).toEqual({ a: 1, b: 2 })
+
+    ref.a = 3
+    expect(ref).toEqual({ a: 3, b: 2 })
+
+    ref.b = 4
+    expect(ref).toEqual({ a: 3, b: 4 })
+
+    ref.c = 5
+    expect(ref).toEqual({ a: 3, b: 4, c: 5 })
+
+    ref.fn = () => 6
+    expect(ref).toEqual({ a: 3, b: 4, c: 5, fn: expect.any(Function) })
+    expect((ref.fn as () => number)()).toBe(6)
+  })
+})
diff --git a/packages/svelte-query/tests/context/context.test.ts b/packages/svelte-query/tests/context/context.svelte.test.ts
similarity index 100%
rename from packages/svelte-query/tests/context/context.test.ts
rename to packages/svelte-query/tests/context/context.svelte.test.ts
diff --git a/packages/svelte-query/tests/createInfiniteQuery/BaseExample.svelte b/packages/svelte-query/tests/createInfiniteQuery/BaseExample.svelte
index ce33e17b90..20d4053d67 100644
--- a/packages/svelte-query/tests/createInfiniteQuery/BaseExample.svelte
+++ b/packages/svelte-query/tests/createInfiniteQuery/BaseExample.svelte
@@ -1,24 +1,32 @@
 <script lang="ts">
+  import { untrack } from 'svelte'
   import { QueryClient } from '@tanstack/query-core'
+  import { sleep } from '@tanstack/query-test-utils'
   import { createInfiniteQuery } from '../../src/index.js'
   import type { QueryObserverResult } from '@tanstack/query-core'
-  import type { Writable } from 'svelte/store'
 
-  export let states: Writable<Array<QueryObserverResult>>
+  let { states }: { states: { value: Array<QueryObserverResult> } } = $props()
 
   const queryClient = new QueryClient()
 
   const query = createInfiniteQuery(
-    {
+    () => ({
       queryKey: ['test'],
-      queryFn: ({ pageParam }) => Number(pageParam),
+      queryFn: async ({ pageParam }) => {
+        await sleep(5)
+        return Number(pageParam)
+      },
       getNextPageParam: (lastPage) => lastPage + 1,
       initialPageParam: 0,
-    },
-    queryClient,
+    }),
+    () => queryClient,
   )
 
-  $: states.update((prev) => [...prev, $query])
+  $effect(() => {
+    // @ts-expect-error
+    // svelte-ignore state_snapshot_uncloneable
+    states.value = [...untrack(() => states.value), $state.snapshot(query)]
+  })
 </script>
 
-<div>Status: {$query.status}</div>
+<div>Status: {query.status}</div>
diff --git a/packages/svelte-query/tests/createInfiniteQuery/SelectExample.svelte b/packages/svelte-query/tests/createInfiniteQuery/SelectExample.svelte
index c96a483842..626122da75 100644
--- a/packages/svelte-query/tests/createInfiniteQuery/SelectExample.svelte
+++ b/packages/svelte-query/tests/createInfiniteQuery/SelectExample.svelte
@@ -1,15 +1,15 @@
 <script lang="ts">
+  import { untrack } from 'svelte'
   import { QueryClient } from '@tanstack/query-core'
   import { createInfiniteQuery } from '../../src/index.js'
   import type { QueryObserverResult } from '@tanstack/query-core'
-  import type { Writable } from 'svelte/store'
 
-  export let states: Writable<Array<QueryObserverResult>>
+  let { states }: { states: { value: Array<QueryObserverResult> } } = $props()
 
   const queryClient = new QueryClient()
 
   const query = createInfiniteQuery(
-    {
+    () => ({
       queryKey: ['test'],
       queryFn: () => Promise.resolve({ count: 1 }),
       select: (data) => ({
@@ -18,11 +18,15 @@
       }),
       getNextPageParam: () => undefined,
       initialPageParam: 0,
-    },
-    queryClient,
+    }),
+    () => queryClient,
   )
 
-  $: states.update((prev) => [...prev, $query])
+  $effect(() => {
+    // @ts-expect-error
+    // svelte-ignore state_snapshot_uncloneable
+    states.value = [...untrack(() => states.value), $state.snapshot(query)]
+  })
 </script>
 
-<div>{$query.data?.pages.join(',')}</div>
+<div>{query.data?.pages.join(',')}</div>
diff --git a/packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.test.ts b/packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.svelte.test.ts
similarity index 83%
rename from packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.test.ts
rename to packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.svelte.test.ts
index d80bc9c706..e1ffb9fd12 100644
--- a/packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.test.ts
+++ b/packages/svelte-query/tests/createInfiniteQuery/createInfiniteQuery.svelte.test.ts
@@ -1,18 +1,17 @@
 import { describe, expect, test } from 'vitest'
 import { render, waitFor } from '@testing-library/svelte'
-import { get, writable } from 'svelte/store'
+import { ref } from '../utils.svelte.js'
 import BaseExample from './BaseExample.svelte'
 import SelectExample from './SelectExample.svelte'
-import type { Writable } from 'svelte/store'
 import type { QueryObserverResult } from '@tanstack/query-core'
 
 describe('createInfiniteQuery', () => {
   test('Return the correct states for a successful query', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
+    let states = ref<Array<QueryObserverResult>>([])
 
     const rendered = render(BaseExample, {
       props: {
-        states: statesStore,
+        states,
       },
     })
 
@@ -20,11 +19,9 @@ describe('createInfiniteQuery', () => {
       expect(rendered.queryByText('Status: success')).toBeInTheDocument()
     })
 
-    const states = get(statesStore)
+    expect(states.value).toHaveLength(2)
 
-    expect(states).toHaveLength(2)
-
-    expect(states[0]).toEqual({
+    expect(states.value[0]).toEqual({
       data: undefined,
       dataUpdatedAt: 0,
       error: null,
@@ -60,7 +57,7 @@ describe('createInfiniteQuery', () => {
       promise: expect.any(Promise),
     })
 
-    expect(states[1]).toEqual({
+    expect(states.value[1]).toEqual({
       data: { pages: [0], pageParams: [0] },
       dataUpdatedAt: expect.any(Number),
       error: null,
@@ -98,11 +95,11 @@ describe('createInfiniteQuery', () => {
   })
 
   test('Select a part of the data', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
+    let states = ref<Array<QueryObserverResult>>([])
 
     const rendered = render(SelectExample, {
       props: {
-        states: statesStore,
+        states,
       },
     })
 
@@ -110,16 +107,14 @@ describe('createInfiniteQuery', () => {
       expect(rendered.queryByText('count: 1')).toBeInTheDocument()
     })
 
-    const states = get(statesStore)
-
-    expect(states).toHaveLength(2)
+    expect(states.value).toHaveLength(2)
 
-    expect(states[0]).toMatchObject({
+    expect(states.value[0]).toMatchObject({
       data: undefined,
       isSuccess: false,
     })
 
-    expect(states[1]).toMatchObject({
+    expect(states.value[1]).toMatchObject({
       data: { pages: ['count: 1'] },
       isSuccess: true,
     })
diff --git a/packages/svelte-query/tests/createMutation/FailureExample.svelte b/packages/svelte-query/tests/createMutation/FailureExample.svelte
index 9855664e8b..a2e59f3bc3 100644
--- a/packages/svelte-query/tests/createMutation/FailureExample.svelte
+++ b/packages/svelte-query/tests/createMutation/FailureExample.svelte
@@ -1,23 +1,23 @@
 <script lang="ts">
-  import { writable } from 'svelte/store'
   import { QueryClient } from '@tanstack/query-core'
   import { createMutation, setQueryClientContext } from '../../src/index.js'
 
-  export let mutationFn: (value: {
-    count: number
-  }) => Promise<{ count: number }>
+  let {
+    mutationFn,
+  }: { mutationFn: (value: { count: number }) => Promise<{ count: number }> } =
+    $props()
 
-  const count = writable(0)
+  let count = $state(0)
 
   const queryClient = new QueryClient()
   setQueryClientContext(queryClient)
 
-  const mutation = createMutation({ mutationFn: mutationFn })
+  const mutation = createMutation(() => ({ mutationFn: mutationFn }))
 </script>
 
-<button on:click={() => $mutation.mutate({ count: ++$count })}>Mutate</button>
+<button onclick={() => mutation.mutate({ count: ++count })}>Mutate</button>
 
-<div>Data: {$mutation.data?.count ?? 'undefined'}</div>
-<div>Status: {$mutation.status}</div>
-<div>Failure Count: {$mutation.failureCount ?? 'undefined'}</div>
-<div>Failure Reason: {$mutation.failureReason ?? 'null'}</div>
+<div>Data: {mutation.data?.count ?? 'undefined'}</div>
+<div>Status: {mutation.status}</div>
+<div>Failure Count: {mutation.failureCount}</div>
+<div>Failure Reason: {mutation.failureReason ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/createMutation/OnSuccessExample.svelte b/packages/svelte-query/tests/createMutation/OnSuccessExample.svelte
index 7f338ede5d..67e73b435a 100644
--- a/packages/svelte-query/tests/createMutation/OnSuccessExample.svelte
+++ b/packages/svelte-query/tests/createMutation/OnSuccessExample.svelte
@@ -11,7 +11,7 @@
   const queryClient = new QueryClient()
   setQueryClientContext(queryClient)
 
-  const mutation = createMutation({
+  const mutation = createMutation(() => ({
     mutationFn: (vars: { count: number }) => Promise.resolve(vars.count),
     onSuccess: (data) => {
       onSuccessMock(data)
@@ -19,9 +19,9 @@
     onSettled: (data) => {
       onSettledMock(data)
     },
-  })
+  }))
 </script>
 
-<button on:click={() => $mutation.mutate({ count: ++$count })}>Mutate</button>
+<button onclick={() => mutation.mutate({ count: ++$count })}>Mutate</button>
 
 <div>Count: {$count}</div>
diff --git a/packages/svelte-query/tests/createMutation/ResetExample.svelte b/packages/svelte-query/tests/createMutation/ResetExample.svelte
index 5ff0a76f53..0e076ee0bc 100644
--- a/packages/svelte-query/tests/createMutation/ResetExample.svelte
+++ b/packages/svelte-query/tests/createMutation/ResetExample.svelte
@@ -5,16 +5,16 @@
   const queryClient = new QueryClient()
   setQueryClientContext(queryClient)
 
-  const mutation = createMutation({
+  const mutation = createMutation(() => ({
     mutationFn: () => {
       const err = new Error('Expected mock error')
       err.stack = ''
       return Promise.reject(err)
     },
-  })
+  }))
 </script>
 
-<button on:click={() => $mutation.reset()}>Reset</button>
-<button on:click={() => $mutation.mutate()}>Mutate</button>
+<button onclick={() => mutation.reset()}>Reset</button>
+<button onclick={() => mutation.mutate()}>Mutate</button>
 
-<div>Error: {$mutation.error?.message ?? 'undefined'}</div>
+<div>Error: {mutation.error?.message ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/createMutation/createMutation.test.ts b/packages/svelte-query/tests/createMutation/createMutation.svelte.test.ts
similarity index 97%
rename from packages/svelte-query/tests/createMutation/createMutation.test.ts
rename to packages/svelte-query/tests/createMutation/createMutation.svelte.test.ts
index 02650facdb..74ca35b0e4 100644
--- a/packages/svelte-query/tests/createMutation/createMutation.test.ts
+++ b/packages/svelte-query/tests/createMutation/createMutation.svelte.test.ts
@@ -103,6 +103,6 @@ describe('createMutation', () => {
     await waitFor(() => rendered.getByText('Status: success'))
     await waitFor(() => rendered.getByText('Data: 2'))
     await waitFor(() => rendered.getByText('Failure Count: 0'))
-    await waitFor(() => rendered.getByText('Failure Reason: null'))
+    await waitFor(() => rendered.getByText('Failure Reason: undefined'))
   })
 })
diff --git a/packages/svelte-query/tests/createQueries.svelte.test.ts b/packages/svelte-query/tests/createQueries.svelte.test.ts
new file mode 100644
index 0000000000..c648942483
--- /dev/null
+++ b/packages/svelte-query/tests/createQueries.svelte.test.ts
@@ -0,0 +1,934 @@
+import { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest'
+import { QueryClient, createQueries } from '../src/index.js'
+import { promiseWithResolvers, withEffectRoot } from './utils.svelte.js'
+import type {
+  CreateQueryOptions,
+  CreateQueryResult,
+  QueryFunction,
+  QueryFunctionContext,
+  QueryKey,
+  skipToken,
+} from '../src/index.js'
+
+describe('createQueries', () => {
+  const queryClient = new QueryClient()
+
+  afterEach(() => {
+    queryClient.clear()
+  })
+
+  it(
+    'should return the correct states',
+    withEffectRoot(async () => {
+      const key1 = ['test-1']
+      const key2 = ['test-2']
+      const results: Array<Array<CreateQueryResult>> = []
+      const { promise: promise1, resolve: resolve1 } = promiseWithResolvers()
+      const { promise: promise2, resolve: resolve2 } = promiseWithResolvers()
+
+      const result = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => promise1,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => promise2,
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        results.push([{ ...result[0] }, { ...result[1] }])
+      })
+
+      resolve1(1)
+
+      await vi.waitFor(() => expect(result[0].data).toBe(1))
+
+      resolve2(2)
+      await vi.waitFor(() => expect(result[1].data).toBe(2))
+
+      expect(results.length).toBe(3)
+      expect(results[0]).toMatchObject([
+        { data: undefined },
+        { data: undefined },
+      ])
+      expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])
+      expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])
+    }),
+  )
+
+  it(
+    'handles type parameter - tuple of tuples',
+    withEffectRoot(() => {
+      const key1 = ['test-key-1']
+      const key2 = ['test-key-2']
+      const key3 = ['test-key-3']
+
+      const result1 = createQueries<
+        [[number], [string], [Array<string>, boolean]]
+      >(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 1,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+            },
+            {
+              queryKey: key3,
+              queryFn: () => ['string[]'],
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result1[0]).toEqualTypeOf<
+        CreateQueryResult<number, unknown>
+      >()
+      expectTypeOf(result1[1]).toEqualTypeOf<
+        CreateQueryResult<string, unknown>
+      >()
+      expectTypeOf(result1[2]).toEqualTypeOf<
+        CreateQueryResult<Array<string>, boolean>
+      >()
+      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()
+      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()
+      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()
+      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()
+
+      // TData (3rd element) takes precedence over TQueryFnData (1st element)
+      const result2 = createQueries<
+        [[string, unknown, string], [string, unknown, number]]
+      >(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return a.toLowerCase()
+              },
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return parseInt(a)
+              },
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result2[0]).toEqualTypeOf<
+        CreateQueryResult<string, unknown>
+      >()
+      expectTypeOf(result2[1]).toEqualTypeOf<
+        CreateQueryResult<number, unknown>
+      >()
+      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()
+      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()
+
+      // types should be enforced
+      createQueries<[[string, unknown, string], [string, boolean, number]]>(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return a.toLowerCase()
+              },
+              placeholderData: 'string',
+              // @ts-expect-error (initialData: string)
+              initialData: 123,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return parseInt(a)
+              },
+              placeholderData: 'string',
+              // @ts-expect-error (initialData: string)
+              initialData: 123,
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      // field names should be enforced
+      createQueries<[[string]]>(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+    }),
+  )
+
+  it(
+    'handles type parameter - tuple of objects',
+    withEffectRoot(() => {
+      const key1 = ['test-key-1']
+      const key2 = ['test-key-2']
+      const key3 = ['test-key-3']
+
+      const result1 = createQueries<
+        [
+          { queryFnData: number },
+          { queryFnData: string },
+          { queryFnData: Array<string>; error: boolean },
+        ]
+      >(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 1,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+            },
+            {
+              queryKey: key3,
+              queryFn: () => ['string[]'],
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result1[0]).toEqualTypeOf<
+        CreateQueryResult<number, unknown>
+      >()
+      expectTypeOf(result1[1]).toEqualTypeOf<
+        CreateQueryResult<string, unknown>
+      >()
+      expectTypeOf(result1[2]).toEqualTypeOf<
+        CreateQueryResult<Array<string>, boolean>
+      >()
+      expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()
+      expectTypeOf(result1[1].data).toEqualTypeOf<string | undefined>()
+      expectTypeOf(result1[2].data).toEqualTypeOf<Array<string> | undefined>()
+      expectTypeOf(result1[2].error).toEqualTypeOf<boolean | null>()
+
+      // TData (data prop) takes precedence over TQueryFnData (queryFnData prop)
+      const result2 = createQueries<
+        [
+          { queryFnData: string; data: string },
+          { queryFnData: string; data: number },
+        ]
+      >(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return a.toLowerCase()
+              },
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return parseInt(a)
+              },
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result2[0]).toEqualTypeOf<
+        CreateQueryResult<string, unknown>
+      >()
+      expectTypeOf(result2[1]).toEqualTypeOf<
+        CreateQueryResult<number, unknown>
+      >()
+      expectTypeOf(result2[0].data).toEqualTypeOf<string | undefined>()
+      expectTypeOf(result2[1].data).toEqualTypeOf<number | undefined>()
+
+      // can pass only TData (data prop) although TQueryFnData will be left unknown
+      const result3 = createQueries<[{ data: string }, { data: number }]>(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<unknown>()
+                return a as string
+              },
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<unknown>()
+                return a as number
+              },
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result3[0]).toEqualTypeOf<
+        CreateQueryResult<string, unknown>
+      >()
+      expectTypeOf(result3[1]).toEqualTypeOf<
+        CreateQueryResult<number, unknown>
+      >()
+      expectTypeOf(result3[0].data).toEqualTypeOf<string | undefined>()
+      expectTypeOf(result3[1].data).toEqualTypeOf<number | undefined>()
+
+      // types should be enforced
+      createQueries<
+        [
+          { queryFnData: string; data: string },
+          { queryFnData: string; data: number; error: boolean },
+        ]
+      >(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return a.toLowerCase()
+              },
+              placeholderData: 'string',
+              // @ts-expect-error (initialData: string)
+              initialData: 123,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+              select: (a) => {
+                expectTypeOf(a).toEqualTypeOf<string>()
+                return parseInt(a)
+              },
+              placeholderData: 'string',
+              // @ts-expect-error (initialData: string)
+              initialData: 123,
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      // field names should be enforced
+      createQueries<[{ queryFnData: string }]>(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+    }),
+  )
+
+  it(
+    'handles array literal without type parameter to infer result type',
+    withEffectRoot(() => {
+      const key1 = ['test-key-1']
+      const key2 = ['test-key-2']
+      const key3 = ['test-key-3']
+      const key4 = ['test-key-4']
+
+      // Array.map preserves TQueryFnData
+      const result1 = createQueries(
+        () => ({
+          queries: Array(50).map((_, i) => ({
+            queryKey: ['key', i] as const,
+            queryFn: () => i + 10,
+          })),
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result1).toEqualTypeOf<
+        Array<CreateQueryResult<number, Error>>
+      >()
+      if (result1[0]) {
+        expectTypeOf(result1[0].data).toEqualTypeOf<number | undefined>()
+      }
+
+      // Array.map preserves TData
+      const result2 = createQueries(
+        () => ({
+          queries: Array(50).map((_, i) => ({
+            queryKey: ['key', i] as const,
+            queryFn: () => i + 10,
+            select: (data: number) => data.toString(),
+          })),
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result2).toEqualTypeOf<
+        Array<CreateQueryResult<string, Error>>
+      >()
+
+      const result3 = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 1,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+            },
+            {
+              queryKey: key3,
+              queryFn: () => ['string[]'],
+              select: () => 123,
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result3[0]).toEqualTypeOf<CreateQueryResult<number, Error>>()
+      expectTypeOf(result3[1]).toEqualTypeOf<CreateQueryResult<string, Error>>()
+      expectTypeOf(result3[2]).toEqualTypeOf<CreateQueryResult<number, Error>>()
+      expectTypeOf(result3[0].data).toEqualTypeOf<number | undefined>()
+      expectTypeOf(result3[1].data).toEqualTypeOf<string | undefined>()
+      // select takes precedence over queryFn
+      expectTypeOf(result3[2].data).toEqualTypeOf<number | undefined>()
+
+      // initialData/placeholderData are enforced
+      createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+              placeholderData: 'string',
+              // @ts-expect-error (initialData: string)
+              initialData: 123,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 123,
+              // @ts-expect-error (placeholderData: number)
+              placeholderData: 'string',
+              initialData: 123,
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      // select params are "indirectly" enforced
+      createQueries(
+        () => ({
+          queries: [
+            // unfortunately TS will not suggest the type for you
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+            },
+            // however you can add a type to the callback
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+            },
+            // the type you do pass is enforced
+            {
+              queryKey: key3,
+              queryFn: () => 'string',
+            },
+            {
+              queryKey: key4,
+              queryFn: () => 'string',
+              select: (a: string) => parseInt(a),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      // callbacks are also indirectly enforced with Array.map
+      createQueries(
+        () => ({
+          queries: Array(50).map((_, i) => ({
+            queryKey: ['key', i] as const,
+            queryFn: () => i + 10,
+            select: (data: number) => data.toString(),
+          })),
+        }),
+        () => queryClient,
+      )
+
+      // results inference works when all the handlers are defined
+      const result4 = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+            },
+            {
+              queryKey: key2,
+              queryFn: () => 'string',
+            },
+            {
+              queryKey: key4,
+              queryFn: () => 'string',
+              select: (a: string) => parseInt(a),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result4[0]).toEqualTypeOf<CreateQueryResult<string, Error>>()
+      expectTypeOf(result4[1]).toEqualTypeOf<CreateQueryResult<string, Error>>()
+      expectTypeOf(result4[2]).toEqualTypeOf<CreateQueryResult<number, Error>>()
+
+      // handles when queryFn returns a Promise
+      const result5 = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => Promise.resolve('string'),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result5[0]).toEqualTypeOf<CreateQueryResult<string, Error>>()
+
+      // Array as const does not throw error
+      const result6 = createQueries(
+        () =>
+          ({
+            queries: [
+              {
+                queryKey: ['key1'],
+                queryFn: () => 'string',
+              },
+              {
+                queryKey: ['key1'],
+                queryFn: () => 123,
+              },
+            ],
+          }) as const,
+        () => queryClient,
+      )
+
+      expectTypeOf(result6[0]).toEqualTypeOf<CreateQueryResult<string, Error>>()
+      expectTypeOf(result6[1]).toEqualTypeOf<CreateQueryResult<number, Error>>()
+
+      // field names should be enforced - array literal
+      createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => 'string',
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      // field names should be enforced - Array.map() result
+      createQueries(
+        () => ({
+          // @ts-expect-error (invalidField)
+          queries: Array(10).map(() => ({
+            someInvalidField: '',
+          })),
+        }),
+        () => queryClient,
+      )
+
+      // supports queryFn using fetch() to return Promise<any> - Array.map() result
+      createQueries(
+        () => ({
+          queries: Array(50).map((_, i) => ({
+            queryKey: ['key', i] as const,
+            queryFn: () =>
+              fetch('return Promise<any>').then((resp) => resp.json()),
+          })),
+        }),
+        () => queryClient,
+      )
+
+      // supports queryFn using fetch() to return Promise<any> - array literal
+      createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () =>
+                fetch('return Promise<any>').then((resp) => resp.json()),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+    }),
+  )
+
+  it(
+    'handles strongly typed queryFn factories and createQueries wrappers',
+    withEffectRoot(() => {
+      // QueryKey + queryFn factory
+      type QueryKeyA = ['queryA']
+      const getQueryKeyA = (): QueryKeyA => ['queryA']
+      type GetQueryFunctionA = () => QueryFunction<number, QueryKeyA>
+      const getQueryFunctionA: GetQueryFunctionA = () => () => {
+        return 1
+      }
+      type SelectorA = (data: number) => [number, string]
+      const getSelectorA = (): SelectorA => (data) => [data, data.toString()]
+
+      type QueryKeyB = ['queryB', string]
+      const getQueryKeyB = (id: string): QueryKeyB => ['queryB', id]
+      type GetQueryFunctionB = () => QueryFunction<string, QueryKeyB>
+      const getQueryFunctionB: GetQueryFunctionB = () => () => {
+        return '1'
+      }
+      type SelectorB = (data: string) => [string, number]
+      const getSelectorB = (): SelectorB => (data) => [data, +data]
+
+      // Wrapper with strongly typed array-parameter
+      function useWrappedQueries<
+        TQueryFnData,
+        TError,
+        TData,
+        TQueryKey extends QueryKey,
+      >(
+        queries: Array<
+          CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>
+        >,
+      ) {
+        return createQueries(
+          () => ({
+            queries: queries.map(
+              // no need to type the mapped query
+              (query) => {
+                const { queryFn: fn, queryKey: key } = query
+                expectTypeOf(fn).toEqualTypeOf<
+                  | typeof skipToken
+                  | QueryFunction<TQueryFnData, TQueryKey, never>
+                  | undefined
+                >()
+                return {
+                  queryKey: key,
+                  queryFn: fn
+                    ? (ctx: QueryFunctionContext<TQueryKey>) => {
+                        // eslint-disable-next-line vitest/valid-expect
+                        expectTypeOf<TQueryKey>(ctx.queryKey)
+                        return (
+                          fn as QueryFunction<TQueryFnData, TQueryKey>
+                        ).call({}, ctx)
+                      }
+                    : undefined,
+                }
+              },
+            ),
+          }),
+          () => queryClient,
+        )
+      }
+
+      const result = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: getQueryKeyA(),
+              queryFn: getQueryFunctionA(),
+            },
+            {
+              queryKey: getQueryKeyB('id'),
+              queryFn: getQueryFunctionB(),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(result[0]).toEqualTypeOf<CreateQueryResult<number, Error>>()
+      expectTypeOf(result[1]).toEqualTypeOf<CreateQueryResult<string, Error>>()
+
+      const withSelector = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: getQueryKeyA(),
+              queryFn: getQueryFunctionA(),
+              select: getSelectorA(),
+            },
+            {
+              queryKey: getQueryKeyB('id'),
+              queryFn: getQueryFunctionB(),
+              select: getSelectorB(),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      expectTypeOf(withSelector[0]).toEqualTypeOf<
+        CreateQueryResult<[number, string], Error>
+      >()
+      expectTypeOf(withSelector[1]).toEqualTypeOf<
+        CreateQueryResult<[string, number], Error>
+      >()
+
+      const withWrappedQueries = useWrappedQueries(
+        Array(10).map(() => ({
+          queryKey: getQueryKeyA(),
+          queryFn: getQueryFunctionA(),
+          select: getSelectorA(),
+        })),
+      )
+
+      expectTypeOf(withWrappedQueries).toEqualTypeOf<
+        Array<CreateQueryResult<number, Error>>
+      >()
+    }),
+  )
+
+  it(
+    'should track results',
+    withEffectRoot(async () => {
+      const key1 = ['test-track-results']
+      const results: Array<Array<CreateQueryResult>> = []
+      let count = 0
+
+      const result = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => Promise.resolve(++count),
+            },
+          ],
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        results.push([result[0]])
+      })
+
+      await vi.waitFor(() => expect(result[0].data).toBe(1))
+
+      expect(results.length).toBe(2)
+      expect(results[0]).toMatchObject([{ data: undefined }])
+      expect(results[1]).toMatchObject([{ data: 1 }])
+
+      // Trigger refetch
+      result[0].refetch()
+
+      await vi.waitFor(() => expect(result[0].data).toBe(2))
+
+      // Only one render for data update, no render for isFetching transition
+      expect(results.length).toBe(3)
+      expect(results[2]).toMatchObject([{ data: 2 }])
+    }),
+  )
+
+  it(
+    'should combine queries',
+    withEffectRoot(async () => {
+      const key1 = ['test-combine-1']
+      const key2 = ['test-combine-2']
+
+      const { promise: promise1, resolve: resolve1 } =
+        promiseWithResolvers<string>()
+      const { promise: promise2, resolve: resolve2 } =
+        promiseWithResolvers<string>()
+
+      const queries = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => promise1,
+            },
+            {
+              queryKey: key2,
+              queryFn: () => promise2,
+            },
+          ],
+          combine: (results) => {
+            return {
+              combined: true,
+              res: results
+                .flatMap((res) => (res.data ? [res.data] : []))
+                .join(','),
+            }
+          },
+        }),
+        () => queryClient,
+      )
+
+      // Initially both queries are loading
+      expect(queries).toEqual({
+        combined: true,
+        res: '',
+      })
+
+      // Resolve the first query
+      resolve1('first result')
+      await vi.waitFor(() => expect(queries.res).toBe('first result'))
+
+      // Resolve the second query
+      resolve2('second result')
+      await vi.waitFor(() =>
+        expect(queries.res).toBe('first result,second result'),
+      )
+
+      expect(queries).toEqual({
+        combined: true,
+        res: 'first result,second result',
+      })
+    }),
+  )
+
+  it(
+    'should track property access through combine function',
+    withEffectRoot(async () => {
+      const key1 = ['test-track-combine-1']
+      const key2 = ['test-track-combine-2']
+      let count = 0
+      const results: Array<unknown> = []
+
+      const { promise: promise1, resolve: resolve1 } =
+        promiseWithResolvers<string>()
+      const { promise: promise2, resolve: resolve2 } =
+        promiseWithResolvers<string>()
+      const { promise: promise3, resolve: resolve3 } =
+        promiseWithResolvers<string>()
+      const { promise: promise4, resolve: resolve4 } =
+        promiseWithResolvers<string>()
+
+      const queries = createQueries(
+        () => ({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: () => (count === 0 ? promise1 : promise3),
+            },
+            {
+              queryKey: key2,
+              queryFn: () => (count === 0 ? promise2 : promise4),
+            },
+          ],
+          combine: (queryResults) => {
+            return {
+              combined: true,
+              refetch: () =>
+                Promise.all(queryResults.map((res) => res.refetch())),
+              res: queryResults
+                .flatMap((res) => (res.data ? [res.data] : []))
+                .join(','),
+            }
+          },
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        results.push({ ...queries })
+      })
+
+      // Initially both queries are loading
+      await vi.waitFor(() =>
+        expect(results[0]).toStrictEqual({
+          combined: true,
+          refetch: expect.any(Function),
+          res: '',
+        }),
+      )
+
+      // Resolve the first query
+      resolve1('first result ' + count)
+      await vi.waitFor(() => expect(queries.res).toBe('first result 0'))
+
+      expect(results[1]).toStrictEqual({
+        combined: true,
+        refetch: expect.any(Function),
+        res: 'first result 0',
+      })
+
+      // Resolve the second query
+      resolve2('second result ' + count)
+      await vi.waitFor(() =>
+        expect(queries.res).toBe('first result 0,second result 0'),
+      )
+
+      expect(results[2]).toStrictEqual({
+        combined: true,
+        refetch: expect.any(Function),
+        res: 'first result 0,second result 0',
+      })
+
+      // Increment count and refetch
+      count++
+      queries.refetch()
+
+      // Resolve the refetched queries
+      resolve3('first result ' + count)
+      resolve4('second result ' + count)
+
+      await vi.waitFor(() =>
+        expect(queries.res).toBe('first result 1,second result 1'),
+      )
+
+      const length = results.length
+      expect(results.at(-1)).toStrictEqual({
+        combined: true,
+        refetch: expect.any(Function),
+        res: 'first result 1,second result 1',
+      })
+
+      // Refetch again but with the same data
+      await queries.refetch()
+
+      // No further re-render because data didn't change
+      expect(results.length).toBe(length)
+    }),
+  )
+})
diff --git a/packages/svelte-query/tests/createQueries.test-d.ts b/packages/svelte-query/tests/createQueries.test-d.ts
new file mode 100644
index 0000000000..016f5a53a5
--- /dev/null
+++ b/packages/svelte-query/tests/createQueries.test-d.ts
@@ -0,0 +1,34 @@
+import { describe, expectTypeOf, it } from 'vitest'
+import { createQueries, queryOptions } from '../src/index.js'
+import type { CreateQueryResult } from '../src/index.js'
+
+describe('createQueries', () => {
+  it('should return correct data for dynamic queries with mixed result types', () => {
+    const Queries1 = {
+      get: () =>
+        queryOptions({
+          queryKey: ['key1'],
+          queryFn: () => Promise.resolve(1),
+        }),
+    }
+    const Queries2 = {
+      get: () =>
+        queryOptions({
+          queryKey: ['key2'],
+          queryFn: () => Promise.resolve(true),
+        }),
+    }
+
+    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))
+    const result = createQueries(() => ({
+      queries: [...queries1List, { ...Queries2.get() }],
+    }))
+
+    expectTypeOf(result).toEqualTypeOf<
+      [
+        ...Array<CreateQueryResult<number, Error>>,
+        CreateQueryResult<boolean, Error>,
+      ]
+    >()
+  })
+})
diff --git a/packages/svelte-query/tests/createQueries/BaseExample.svelte b/packages/svelte-query/tests/createQueries/BaseExample.svelte
deleted file mode 100644
index b9b5ae7c47..0000000000
--- a/packages/svelte-query/tests/createQueries/BaseExample.svelte
+++ /dev/null
@@ -1,17 +0,0 @@
-<script lang="ts">
-  import { createQueries } from '../../src/index.js'
-  import type { QueryClient } from '@tanstack/query-core'
-  import type { QueriesOptions } from '../../src/index.js'
-
-  export let options: {
-    queries: [...QueriesOptions<any>]
-  }
-  export let queryClient: QueryClient
-
-  const queries = createQueries(options, queryClient)
-</script>
-
-{#each $queries as query, index}
-  <div>Status {index + 1}: {query.status}</div>
-  <div>Data {index + 1}: {query.data}</div>
-{/each}
diff --git a/packages/svelte-query/tests/createQueries/CombineExample.svelte b/packages/svelte-query/tests/createQueries/CombineExample.svelte
deleted file mode 100644
index 0d1ac9c531..0000000000
--- a/packages/svelte-query/tests/createQueries/CombineExample.svelte
+++ /dev/null
@@ -1,32 +0,0 @@
-<script lang="ts">
-  import { createQueries } from '../../src/index.js'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { QueryClient } from '@tanstack/query-core'
-
-  export let queryClient: QueryClient
-
-  const ids = [1, 2, 3]
-
-  const queries = createQueries(
-    {
-      queries: ids.map((id) => ({
-        queryKey: [id],
-        queryFn: async () => {
-          await sleep(5)
-          return id
-        },
-      })),
-      combine: (results) => {
-        return {
-          isPending: results.some((result) => result.isPending),
-          isSuccess: results.every((result) => result.isSuccess),
-          data: results.map((res) => res.data).join(','),
-        }
-      },
-    },
-    queryClient,
-  )
-</script>
-
-<div>isPending: {$queries.isPending}</div>
-<div>Data: {$queries.data ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/createQueries/createQueries.test-d.ts b/packages/svelte-query/tests/createQueries/createQueries.test-d.ts
deleted file mode 100644
index 0c860ab134..0000000000
--- a/packages/svelte-query/tests/createQueries/createQueries.test-d.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import { describe, expectTypeOf, test } from 'vitest'
-import { get } from 'svelte/store'
-import { skipToken } from '@tanstack/query-core'
-import { createQueries, queryOptions } from '../../src/index.js'
-import type { Readable } from 'svelte/store'
-import type { OmitKeyof, QueryObserverResult } from '@tanstack/query-core'
-import type { CreateQueryOptions } from '../../src/index.js'
-
-describe('createQueries', () => {
-  test('TData should be defined when passed through queryOptions', () => {
-    const options = queryOptions({
-      queryKey: ['key'],
-      queryFn: () => {
-        return {
-          wow: true,
-        }
-      },
-      initialData: {
-        wow: true,
-      },
-    })
-    const queryResults = createQueries({ queries: [options] })
-
-    const data = get(queryResults)[0].data
-
-    expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
-  })
-
-  test('Allow custom hooks using UseQueryOptions', () => {
-    type Data = string
-
-    const useCustomQueries = (
-      options?: OmitKeyof<CreateQueryOptions<Data>, 'queryKey' | 'queryFn'>,
-    ) => {
-      return createQueries({
-        queries: [
-          {
-            ...options,
-            queryKey: ['todos-key'],
-            queryFn: () => Promise.resolve('data'),
-          },
-        ],
-      })
-    }
-
-    const query = useCustomQueries()
-    const data = get(query)[0].data
-
-    expectTypeOf(data).toEqualTypeOf<Data | undefined>()
-  })
-
-  test('TData should have correct type when conditional skipToken is passed', () => {
-    const queryResults = createQueries({
-      queries: [
-        {
-          queryKey: ['withSkipToken'],
-          queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),
-        },
-      ],
-    })
-
-    const firstResult = get(queryResults)[0]
-
-    expectTypeOf(firstResult).toEqualTypeOf<
-      QueryObserverResult<number, Error>
-    >()
-    expectTypeOf(firstResult.data).toEqualTypeOf<number | undefined>()
-  })
-
-  test('should return correct data for dynamic queries with mixed result types', () => {
-    const Queries1 = {
-      get: () =>
-        queryOptions({
-          queryKey: ['key1'],
-          queryFn: () => Promise.resolve(1),
-        }),
-    }
-    const Queries2 = {
-      get: () =>
-        queryOptions({
-          queryKey: ['key2'],
-          queryFn: () => Promise.resolve(true),
-        }),
-    }
-
-    const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))
-    const result = createQueries({
-      queries: [...queries1List, { ...Queries2.get() }],
-    })
-
-    expectTypeOf(result).toEqualTypeOf<
-      Readable<
-        [
-          ...Array<QueryObserverResult<number, Error>>,
-          QueryObserverResult<boolean, Error>,
-        ]
-      >
-    >()
-
-    expectTypeOf(get(result)[0].data).toEqualTypeOf<
-      number | boolean | undefined
-    >()
-  })
-})
diff --git a/packages/svelte-query/tests/createQueries/createQueries.test.ts b/packages/svelte-query/tests/createQueries/createQueries.test.ts
deleted file mode 100644
index f67441bd66..0000000000
--- a/packages/svelte-query/tests/createQueries/createQueries.test.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { describe, expect, test } from 'vitest'
-import { render, waitFor } from '@testing-library/svelte'
-import { QueryClient } from '@tanstack/query-core'
-import { sleep } from '@tanstack/query-test-utils'
-import BaseExample from './BaseExample.svelte'
-import CombineExample from './CombineExample.svelte'
-
-describe('createQueries', () => {
-  test('Render and wait for success', async () => {
-    const rendered = render(BaseExample, {
-      props: {
-        options: {
-          queries: [
-            {
-              queryKey: ['key-1'],
-              queryFn: async () => {
-                await sleep(5)
-                return 'Success 1'
-              },
-            },
-            {
-              queryKey: ['key-2'],
-              queryFn: async () => {
-                await sleep(5)
-                return 'Success 2'
-              },
-            },
-          ],
-        },
-        queryClient: new QueryClient(),
-      },
-    })
-
-    await waitFor(() => {
-      expect(rendered.getByText('Status 1: pending')).toBeInTheDocument()
-      expect(rendered.getByText('Status 2: pending')).toBeInTheDocument()
-    })
-
-    await waitFor(() => {
-      expect(rendered.getByText('Status 1: success')).toBeInTheDocument()
-      expect(rendered.getByText('Status 2: success')).toBeInTheDocument()
-    })
-  })
-
-  test('Combine queries', async () => {
-    const rendered = render(CombineExample, {
-      props: {
-        queryClient: new QueryClient(),
-      },
-    })
-
-    await waitFor(() => {
-      expect(rendered.getByText('isPending: true')).toBeInTheDocument()
-    })
-
-    await waitFor(() => {
-      expect(rendered.getByText('Data: 1,2,3')).toBeInTheDocument()
-    })
-  })
-})
diff --git a/packages/svelte-query/tests/createQuery.svelte.test.ts b/packages/svelte-query/tests/createQuery.svelte.test.ts
new file mode 100644
index 0000000000..f30b557b49
--- /dev/null
+++ b/packages/svelte-query/tests/createQuery.svelte.test.ts
@@ -0,0 +1,1890 @@
+import { flushSync } from 'svelte'
+import { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest'
+import { sleep } from '@tanstack/query-test-utils'
+import { QueryClient, createQuery, keepPreviousData } from '../src/index.js'
+import { promiseWithResolvers, withEffectRoot } from './utils.svelte.js'
+import type { CreateQueryResult } from '../src/index.js'
+
+describe('createQuery', () => {
+  const queryClient = new QueryClient()
+  const queryCache = queryClient.getQueryCache()
+
+  afterEach(() => {
+    queryClient.clear()
+  })
+
+  it(
+    'should return the correct states for a successful query',
+    withEffectRoot(async () => {
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string, Error>(
+        () => ({
+          queryKey: ['test'],
+          queryFn: () => promise,
+        }),
+        () => queryClient,
+      )
+
+      if (query.isPending) {
+        expectTypeOf(query.data).toEqualTypeOf<undefined>()
+        expectTypeOf(query.error).toEqualTypeOf<null>()
+      } else if (query.isLoadingError) {
+        expectTypeOf(query.data).toEqualTypeOf<undefined>()
+        expectTypeOf(query.error).toEqualTypeOf<Error>()
+      } else {
+        expectTypeOf(query.data).toEqualTypeOf<string>()
+        expectTypeOf(query.error).toEqualTypeOf<Error | null>()
+      }
+
+      const promise1 = query.promise
+
+      expect(query).toEqual({
+        data: undefined,
+        dataUpdatedAt: 0,
+        error: null,
+        errorUpdatedAt: 0,
+        failureCount: 0,
+        failureReason: null,
+        errorUpdateCount: 0,
+        isError: false,
+        isFetched: false,
+        isFetchedAfterMount: false,
+        isFetching: true,
+        isPaused: false,
+        isPending: true,
+        isInitialLoading: true,
+        isLoading: true,
+        isLoadingError: false,
+        isPlaceholderData: false,
+        isRefetchError: false,
+        isRefetching: false,
+        isStale: true,
+        isSuccess: false,
+        refetch: expect.any(Function),
+        status: 'pending',
+        fetchStatus: 'fetching',
+        promise: expect.any(Promise),
+      })
+      resolve('resolved')
+      await vi.waitFor(() =>
+        expect(query).toEqual({
+          data: 'resolved',
+          dataUpdatedAt: expect.any(Number),
+          error: null,
+          errorUpdatedAt: 0,
+          failureCount: 0,
+          failureReason: null,
+          errorUpdateCount: 0,
+          isError: false,
+          isFetched: true,
+          isFetchedAfterMount: true,
+          isFetching: false,
+          isPaused: false,
+          isPending: false,
+          isInitialLoading: false,
+          isLoading: false,
+          isLoadingError: false,
+          isPlaceholderData: false,
+          isRefetchError: false,
+          isRefetching: false,
+          isStale: true,
+          isSuccess: true,
+          refetch: expect.any(Function),
+          status: 'success',
+          fetchStatus: 'idle',
+          promise: expect.any(Promise),
+        }),
+      )
+
+      expect(promise1).toBe(query.promise)
+    }),
+  )
+
+  it(
+    'should return the correct states for an unsuccessful query',
+    withEffectRoot(async () => {
+      let count = 0
+      const states: Array<CreateQueryResult> = []
+      const query = createQuery<string, Error>(
+        () => ({
+          queryKey: ['test'],
+          queryFn: () => {
+            return Promise.reject(new Error('rejected #' + ++count))
+          },
+          retry: 1,
+          retryDelay: 1,
+        }),
+        () => queryClient,
+      )
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => expect(query.isError).toBe(true))
+
+      expect(states[0]).toEqual({
+        data: undefined,
+        dataUpdatedAt: 0,
+        error: null,
+        errorUpdatedAt: 0,
+        failureCount: 0,
+        failureReason: null,
+        errorUpdateCount: 0,
+        isError: false,
+        isFetched: false,
+        isFetchedAfterMount: false,
+        isFetching: true,
+        isPaused: false,
+        isPending: true,
+        isInitialLoading: true,
+        isLoading: true,
+        isLoadingError: false,
+        isPlaceholderData: false,
+        isRefetchError: false,
+        isRefetching: false,
+        isStale: true,
+        isSuccess: false,
+        refetch: expect.any(Function),
+        status: 'pending',
+        fetchStatus: 'fetching',
+        promise: expect.any(Promise),
+      })
+
+      expect(states[1]).toEqual({
+        data: undefined,
+        dataUpdatedAt: 0,
+        error: null,
+        errorUpdatedAt: 0,
+        failureCount: 1,
+        failureReason: new Error('rejected #1'),
+        errorUpdateCount: 0,
+        isError: false,
+        isFetched: false,
+        isFetchedAfterMount: false,
+        isFetching: true,
+        isPaused: false,
+        isPending: true,
+        isInitialLoading: true,
+        isLoading: true,
+        isLoadingError: false,
+        isPlaceholderData: false,
+        isRefetchError: false,
+        isRefetching: false,
+        isStale: true,
+        isSuccess: false,
+        refetch: expect.any(Function),
+        status: 'pending',
+        fetchStatus: 'fetching',
+        promise: expect.any(Promise),
+      })
+
+      expect(states[2]).toEqual({
+        data: undefined,
+        dataUpdatedAt: 0,
+        error: new Error('rejected #2'),
+        errorUpdatedAt: expect.any(Number),
+        failureCount: 2,
+        failureReason: new Error('rejected #2'),
+        errorUpdateCount: 1,
+        isError: true,
+        isFetched: true,
+        isFetchedAfterMount: true,
+        isFetching: false,
+        isPaused: false,
+        isPending: false,
+        isInitialLoading: false,
+        isLoading: false,
+        isLoadingError: true,
+        isPlaceholderData: false,
+        isRefetchError: false,
+        isRefetching: false,
+        isStale: true,
+        isSuccess: false,
+        refetch: expect.any(Function),
+        status: 'error',
+        fetchStatus: 'idle',
+        promise: expect.any(Promise),
+      })
+    }),
+  )
+
+  it('should set isFetchedAfterMount to true after a query has been fetched', async () => {
+    const key = ['test']
+
+    await queryClient.prefetchQuery({
+      queryKey: key,
+      queryFn: () => Promise.resolve('prefetched'),
+    })
+
+    await withEffectRoot(async () => {
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = $derived(
+        createQuery<string, Error>(
+          () => ({
+            queryKey: key,
+            queryFn: () => promise,
+          }),
+          () => queryClient,
+        ),
+      )
+
+      expect(query).toEqual(
+        expect.objectContaining({
+          data: 'prefetched',
+          isFetched: true,
+          isFetchedAfterMount: false,
+        }),
+      )
+      resolve('resolved')
+      await vi.waitFor(() =>
+        expect(query).toEqual(
+          expect.objectContaining({
+            data: 'resolved',
+            isFetched: true,
+            isFetchedAfterMount: true,
+          }),
+        ),
+      )
+    })()
+  })
+
+  it(
+    'should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already',
+    withEffectRoot(async () => {
+      const key = ['test']
+      let fetchCount = 0
+
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const { refetch } = createQuery<string, Error>(
+        () => ({
+          queryKey: key,
+          queryFn: () => {
+            fetchCount++
+            return promise
+          },
+          enabled: false,
+          initialData: 'initial',
+        }),
+        () => queryClient,
+      )
+
+      refetch()
+      refetch({ cancelRefetch: false })
+
+      resolve('resolved')
+      await promise
+
+      expect(fetchCount).toBe(1)
+    }),
+  )
+
+  it(
+    'should cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we have data already',
+    withEffectRoot(async () => {
+      const key = ['test']
+      let fetchCount = 0
+
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string, Error>(
+        () => ({
+          queryKey: key,
+          queryFn: async () => {
+            fetchCount++
+            return promise
+          },
+          enabled: false,
+          initialData: 'initialData',
+        }),
+        () => queryClient,
+      )
+
+      // Trigger two refetch close together
+      query.refetch()
+      query.refetch()
+
+      resolve('resolved')
+      await promise
+
+      expect(fetchCount).toBe(2)
+    }),
+  )
+
+  it(
+    'should not cancel an ongoing fetch when refetch is called (cancelRefetch=true) if we do not have data yet',
+    withEffectRoot(async () => {
+      const key = ['test']
+      let fetchCount = 0
+
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string, Error>(
+        () => ({
+          queryKey: key,
+          queryFn: async () => {
+            fetchCount++
+            return promise
+          },
+          enabled: false,
+        }),
+        () => queryClient,
+      )
+
+      // Trigger two refetch close together
+      query.refetch()
+      query.refetch()
+
+      resolve('resolved')
+      await promise
+
+      expect(fetchCount).toBe(1)
+    }),
+  )
+
+  it(
+    'should be able to watch a query without providing a query function',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<string>> = []
+
+      queryClient.setQueryDefaults(key, {
+        queryFn: () => 'data',
+      })
+
+      const query = createQuery<string>(
+        () => ({ queryKey: key }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe('data')
+      })
+
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined })
+      expect(states[1]).toMatchObject({ data: 'data' })
+    }),
+  )
+
+  it('should pick up a query when re-mounting with gcTime 0', async () => {
+    // this needs to be split into two different effect roots because
+    // effects won't pick up dependencies created after the first `await`
+    // -- the two roots effectively emulate two consecutive components being rendered
+    await withEffectRoot(async () => {
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: ['test'],
+          queryFn: () => promise,
+          gcTime: 0,
+          notifyOnChangeProps: 'all',
+        }),
+        () => queryClient,
+      )
+
+      expect(query).toMatchObject({
+        isPending: true,
+        isSuccess: false,
+        isFetching: true,
+      })
+
+      resolve('resolved: 1')
+      await vi.waitFor(() => expect(query.data).toBe('resolved: 1'))
+
+      expect(query).toMatchObject({
+        isPending: false,
+        isSuccess: true,
+        isFetching: false,
+      })
+    })()
+
+    await withEffectRoot(async () => {
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: ['test'],
+          queryFn: () => promise,
+          gcTime: 0,
+          notifyOnChangeProps: 'all',
+        }),
+        () => queryClient,
+      )
+
+      expect(query).toMatchObject({
+        data: 'resolved: 1',
+        isPending: false,
+        isSuccess: true,
+        isFetching: true,
+      })
+
+      resolve('resolved: 2')
+      await vi.waitFor(() => expect(query.data).toBe('resolved: 2'))
+
+      expect(query).toMatchObject({
+        data: 'resolved: 2',
+        isPending: false,
+        isSuccess: true,
+        isFetching: false,
+      })
+    })()
+  })
+
+  it('should not get into an infinite loop when removing a query with gcTime 0 and rerendering', async () => {
+    const key = ['test']
+    const states: Array<CreateQueryResult<string>> = []
+
+    // First mount: render the query and let it fetch
+    await withEffectRoot(async () => {
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve('data'),
+          gcTime: 0,
+          notifyOnChangeProps: ['isPending', 'isSuccess', 'data'],
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe('data')
+      })
+    })()
+
+    // Simulate rerender by removing the query and mounting again
+    await withEffectRoot(async () => {
+      queryClient.removeQueries({ queryKey: key })
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve('data'),
+          gcTime: 0,
+          notifyOnChangeProps: ['isPending', 'isSuccess', 'data'],
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe('data')
+      })
+
+      // Give it time to catch any accidental infinite updates
+      await new Promise((r) => setTimeout(r, 100))
+    })()
+
+    expect(states.length).toBe(4)
+    expect(states[0]).toMatchObject({
+      isPending: true,
+      isSuccess: false,
+      data: undefined,
+    })
+    expect(states[1]).toMatchObject({
+      isPending: false,
+      isSuccess: true,
+      data: 'data',
+    })
+    expect(states[2]).toMatchObject({
+      isPending: true,
+      isSuccess: false,
+      data: undefined,
+    })
+    expect(states[3]).toMatchObject({
+      isPending: false,
+      isSuccess: true,
+      data: 'data',
+    })
+  })
+
+  it(
+    'should fetch when refetchOnMount is false and nothing has been fetched yet',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<string>> = []
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => 'test',
+          refetchOnMount: false,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe('test')
+      })
+
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined })
+      expect(states[1]).toMatchObject({ data: 'test' })
+    }),
+  )
+
+  it(
+    'should not fetch when refetchOnMount is false and data has been fetched already',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<string>> = []
+
+      queryClient.setQueryData(key, 'prefetched')
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => 'test',
+          refetchOnMount: false,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe('prefetched')
+      })
+
+      expect(states.length).toBe(1)
+      expect(states[0]).toMatchObject({ data: 'prefetched' })
+    }),
+  )
+
+  it(
+    'should be able to select a part of the data with select',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<string>> = []
+
+      const query = createQuery<{ name: string }, Error, string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => ({ name: 'test' }),
+          select: (data) => data.name,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe('test')
+      })
+
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined })
+      expect(states[1]).toMatchObject({ data: 'test' })
+    }),
+  )
+
+  it(
+    'should throw an error when a selector throws',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const error = new Error('Select Error')
+      const states: Array<CreateQueryResult<string>> = []
+
+      const query = createQuery<{ name: string }, Error, string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => ({ name: 'test' }),
+          select: () => {
+            throw error
+          },
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.status).toBe('error')
+      })
+
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ status: 'pending', data: undefined })
+      expect(states[1]).toMatchObject({ status: 'error', error })
+    }),
+  )
+
+  it(
+    'should be able to remove a query',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => ++count,
+          notifyOnChangeProps: 'all',
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => expect(query.data).toBe(1))
+
+      queryClient.removeQueries({ queryKey: key })
+      await query.refetch()
+
+      await vi.waitFor(() => expect(query.data).toBe(2))
+
+      expect(states.length).toBe(4)
+      expect(states[0]).toMatchObject({
+        status: 'pending',
+        data: undefined,
+        dataUpdatedAt: 0,
+      })
+      expect(states[1]).toMatchObject({ status: 'success', data: 1 })
+      expect(states[2]).toMatchObject({
+        status: 'pending',
+        data: undefined,
+        dataUpdatedAt: 0,
+      })
+      expect(states[3]).toMatchObject({ status: 'success', data: 2 })
+    }),
+  )
+
+  it(
+    'keeps up-to-date with query key changes',
+    withEffectRoot(async () => {
+      let search = $state('')
+      const states: Array<CreateQueryResult<string>> = []
+
+      const query = createQuery(
+        () => ({
+          queryKey: ['products', search],
+          queryFn: async () => Promise.resolve(search),
+          placeholderData: keepPreviousData,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => expect(query.data).toBe(''))
+      search = 'phone'
+      await vi.waitFor(() => expect(query.data).toBe('phone'))
+
+      expect(states.length).toBe(4)
+      expect(states[0]).toMatchObject({
+        status: 'pending',
+        fetchStatus: 'fetching',
+        data: undefined,
+      })
+      expect(states[1]).toMatchObject({
+        status: 'success',
+        fetchStatus: 'idle',
+        data: '',
+      })
+      expect(states[2]).toMatchObject({
+        status: 'success',
+        fetchStatus: 'fetching',
+        data: '',
+      })
+      expect(states[3]).toMatchObject({
+        status: 'success',
+        fetchStatus: 'idle',
+        data: 'phone',
+      })
+    }),
+  )
+
+  it(
+    'should create a new query when refetching a removed query',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+
+      const query = createQuery(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve(++count),
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => {
+        expect(query.data).toBe(1)
+      })
+
+      queryClient.removeQueries({ queryKey: key })
+      await query.refetch()
+      await vi.waitFor(() => {
+        expect(query.data).toBe(2)
+      })
+
+      expect(states.length).toBe(4)
+      // Initial
+      expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })
+      // Fetched
+      expect(states[1]).toMatchObject({ data: 1 })
+      // Switch
+      expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })
+      // Fetched
+      expect(states[3]).toMatchObject({ data: 2 })
+    }),
+  )
+
+  it(
+    'should share equal data structures between query results',
+    withEffectRoot(async () => {
+      const key = ['test']
+
+      const result1 = [
+        { id: '1', done: false },
+        { id: '2', done: false },
+      ]
+
+      const result2 = [
+        { id: '1', done: false },
+        { id: '2', done: true },
+      ]
+
+      const states: Array<CreateQueryResult<typeof result1>> = []
+
+      let count = 0
+
+      const query = createQuery<typeof result1>(
+        () => ({
+          queryKey: key,
+          queryFn: () => {
+            count++
+            return Promise.resolve(count === 1 ? result1 : result2)
+          },
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => expect(query.data?.[1]?.done).toBe(false))
+      await query.refetch()
+      await vi.waitFor(() => expect(query.data?.[1]?.done).toBe(true))
+
+      expect(states.length).toBe(4)
+
+      const todos = states[1]?.data
+      const todo1 = todos?.[0]
+      const todo2 = todos?.[1]
+
+      const newTodos = states[3]?.data
+      const newTodo1 = newTodos?.[0]
+      const newTodo2 = newTodos?.[1]
+
+      expect(todos).toEqual(result1)
+      expect(newTodos).toEqual(result2)
+      expect(newTodos).not.toBe(todos)
+      expect(newTodo1).toBe(todo1)
+      expect(newTodo2).not.toBe(todo2)
+    }),
+  )
+
+  it(
+    'should use query function from hook when the existing query does not have a query function',
+    withEffectRoot(async () => {
+      const key = ['test']
+
+      queryClient.setQueryData(key, 'set')
+
+      const query = createQuery(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve('fetched'),
+          initialData: 'initial',
+          staleTime: Infinity,
+        }),
+        () => queryClient,
+      )
+
+      await vi.waitFor(() => expect(query.data).toBe('set'))
+      queryClient.refetchQueries({ queryKey: key })
+      await vi.waitFor(() => expect(query.data).toBe('fetched'))
+    }),
+  )
+
+  it(
+    'should update query stale state and refetch when invalidated with invalidateQueries',
+    withEffectRoot(async () => {
+      const key = ['test']
+      let count = 0
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve(++count),
+          staleTime: Infinity,
+        }),
+        () => queryClient,
+      )
+
+      await vi.waitFor(() =>
+        expect(query).toEqual(
+          expect.objectContaining({
+            data: 1,
+            isStale: false,
+            isFetching: false,
+          }),
+        ),
+      )
+      queryClient.invalidateQueries({ queryKey: key })
+      await vi.waitFor(() =>
+        expect(query).toEqual(
+          expect.objectContaining({
+            data: 1,
+            isStale: true,
+            isFetching: true,
+          }),
+        ),
+      )
+      await vi.waitFor(() =>
+        expect(query).toEqual(
+          expect.objectContaining({
+            data: 2,
+            isStale: false,
+            isFetching: false,
+          }),
+        ),
+      )
+    }),
+  )
+
+  it(
+    'should not update disabled query when refetching with refetchQueries',
+    withEffectRoot(async () => {
+      const key = ['test']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve(++count),
+          enabled: false,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await sleep(50)
+
+      expect(states.length).toBe(1)
+      expect(states[0]).toMatchObject({
+        data: undefined,
+        isSuccess: false,
+        isFetching: false,
+        isStale: false,
+      })
+    }),
+  )
+
+  it(
+    'should not refetch disabled query when invalidated with invalidateQueries',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve(++count),
+          enabled: false,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      queryClient.invalidateQueries({ queryKey: key })
+
+      // Wait long enough for the invalidation and potential refetch
+      await sleep(100)
+
+      expect(states.length).toBe(1)
+      expect(states[0]).toMatchObject({
+        data: undefined,
+        isFetching: false,
+        isSuccess: false,
+        isStale: false,
+      })
+    }),
+  )
+
+  it(
+    'should not fetch when switching to a disabled query',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = $state<number>(0)
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: [key, count],
+          queryFn: () => Promise.resolve(count),
+          enabled: count === 0,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      await vi.waitFor(() => expect(query.data).toBe(0))
+      count = 1
+      await vi.waitFor(() => expect(states.length).toBe(3))
+
+      // Fetch query
+      expect(states[0]).toMatchObject({
+        isFetching: true,
+        isSuccess: false,
+      })
+      // Fetched query
+      expect(states[1]).toMatchObject({
+        data: 0,
+        isFetching: false,
+        isSuccess: true,
+      })
+      // Switch to disabled query
+      expect(states[2]).toMatchObject({
+        isFetching: false,
+        isSuccess: false,
+      })
+    }),
+  )
+
+  it(
+    'should keep the previous data when placeholderData is set',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = $state(0)
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: [key, count],
+          queryFn: () => Promise.resolve(count),
+          placeholderData: keepPreviousData,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the initial fetch to complete
+      await vi.waitFor(() => expect(query.data).toBe(0))
+
+      // Update count to trigger a new fetch
+      count = 1
+
+      // Wait for all state updates to complete
+      await vi.waitFor(() => expect(states.length).toBe(4))
+
+      // Initial
+      expect(states[0]).toMatchObject({
+        data: undefined,
+        isFetching: true,
+        isSuccess: false,
+        isPlaceholderData: false,
+      })
+      // Fetched
+      expect(states[1]).toMatchObject({
+        data: 0,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+      // Set state
+      expect(states[2]).toMatchObject({
+        data: 0,
+        isFetching: true,
+        isSuccess: true,
+        isPlaceholderData: true,
+      })
+      // New data
+      expect(states[3]).toMatchObject({
+        data: 1,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+    }),
+  )
+
+  it(
+    'should not show initial data from next query if placeholderData is set',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = $state<number>(0)
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: [key, count],
+          queryFn: () => Promise.resolve(count),
+          initialData: 99,
+          placeholderData: keepPreviousData,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the initial fetch to complete
+      await vi.waitFor(() => expect(query.data).toBe(0))
+
+      // Update count to trigger a new fetch
+      count = 1
+
+      // Wait for the new fetch to complete
+      await vi.waitFor(() => expect(query.data).toBe(1))
+
+      // Wait for all state updates to complete
+      await vi.waitFor(() => expect(states.length).toBe(4))
+
+      // Initial
+      expect(states[0]).toMatchObject({
+        data: 99,
+        isFetching: true,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+      // Fetched
+      expect(states[1]).toMatchObject({
+        data: 0,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+      // Set state
+      expect(states[2]).toMatchObject({
+        data: 99,
+        isFetching: true,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+      // New data
+      expect(states[3]).toMatchObject({
+        data: 1,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+    }),
+  )
+
+  it(
+    'should keep the previous data on disabled query when placeholderData is set and switching query key multiple times',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+
+      // Set initial query data
+      queryClient.setQueryData([key, 10], 10)
+
+      let count = $state(10)
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: [key, count],
+          queryFn: () => Promise.resolve(count),
+          enabled: false,
+          placeholderData: keepPreviousData,
+          notifyOnChangeProps: 'all',
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // let that effect ^ run to push the initial state
+      flushSync()
+      flushSync(() => (count = 11))
+      flushSync(() => (count = 12))
+      await query.refetch()
+      // Wait for all operations to complete
+      await vi.waitFor(() => expect(query.data).toBe(12))
+
+      // Disabled query
+      expect(states[0]).toMatchObject({
+        data: 10,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+      // Set state (11)
+      expect(states[1]).toMatchObject({
+        data: 10,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: true,
+      })
+      // Set state (12)
+      expect(states[2]).toMatchObject({
+        data: 10,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: true,
+      })
+      // Refetch
+      expect(states[3]).toMatchObject({
+        data: 10,
+        isFetching: true,
+        isSuccess: true,
+        isPlaceholderData: true,
+      })
+      // Refetch done
+      expect(states[4]).toMatchObject({
+        data: 12,
+        isFetching: false,
+        isSuccess: true,
+        isPlaceholderData: false,
+      })
+    }),
+  )
+
+  it(
+    'should use the correct query function when components use different configurations',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      const { promise, resolve } = promiseWithResolvers<number>()
+
+      // Simulate FirstComponent
+      const firstQuery = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => promise,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...firstQuery })
+      })
+
+      // Simulate SecondComponent
+      createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => 2,
+        }),
+        () => queryClient,
+      )
+
+      // Resolve the first query
+      resolve(1)
+
+      // Wait for the first query to complete
+      await vi.waitFor(() => expect(firstQuery.data).toBe(1))
+
+      // Refetch the first query
+      await firstQuery.refetch()
+
+      // Wait for all state updates to complete
+      await vi.waitFor(() => expect(states.length).toBe(4))
+
+      expect(states[0]).toMatchObject({
+        data: undefined,
+      })
+      expect(states[1]).toMatchObject({
+        data: 1,
+      })
+      expect(states[2]).toMatchObject({
+        data: 1,
+      })
+      // This state should be 1 instead of 2
+      expect(states[3]).toMatchObject({
+        data: 1,
+      })
+    }),
+  )
+
+  it.todo(
+    'should be able to set different stale times for a query',
+    async () => {
+      /**
+       * TODO: There's a super weird bug with this test, and I think it's caused by a race condition in query-core.
+       *
+       * If you add this to the top `updateResult` in `packages/query-core/src/queryObserver.ts:647`:
+       * ```
+       * for (let i = 0; i < 10_000_000; i++) {
+       *   continue
+       * }
+       * ```
+       *
+       * This test will miraculously start to pass. I'm suspicious that there's some race condition between props
+       * being tracked and `updateResult` being called, but that _should_ be fixed by `notifyOnChangeProps: 'all'`,
+       * and that's not doing anything.
+       *
+       * This test will also start to magically pass if you put `$inspect(firstQuery)` before `vi.waitFor` near
+       * the end of the test.
+       */
+
+      const key = ['test-key']
+      const states1: Array<CreateQueryResult<string>> = []
+      const states2: Array<CreateQueryResult<string>> = []
+
+      // Prefetch the query
+      await queryClient.prefetchQuery({
+        queryKey: key,
+        queryFn: async () => {
+          await sleep(10)
+          return 'prefetch'
+        },
+      })
+
+      await vi.waitFor(() =>
+        expect(queryClient.getQueryState(key)?.data).toBe('prefetch'),
+      )
+
+      await withEffectRoot(async () => {
+        const firstQuery = createQuery<string>(
+          () => ({
+            queryKey: key,
+            queryFn: () => Promise.resolve('one'),
+            staleTime: 100,
+          }),
+          () => queryClient,
+        )
+
+        $effect(() => {
+          states1.push({ ...firstQuery })
+        })
+
+        const secondQuery = createQuery<string>(
+          () => ({
+            queryKey: key,
+            queryFn: () => Promise.resolve('two'),
+            staleTime: 10,
+          }),
+          () => queryClient,
+        )
+
+        $effect(() => {
+          states2.push({ ...secondQuery })
+        })
+
+        await vi.waitFor(() => {
+          expect(firstQuery).toMatchObject({ data: 'two', isStale: true })
+          expect(secondQuery).toMatchObject({ data: 'two', isStale: true })
+        })
+
+        expect(states1).toMatchObject([
+          // First render
+          {
+            data: 'prefetch',
+            isStale: false,
+          },
+          // Second createQuery started fetching
+          {
+            data: 'prefetch',
+            isStale: false,
+          },
+          // Second createQuery data came in
+          {
+            data: 'two',
+            isStale: false,
+          },
+          // Data became stale after 100ms
+          {
+            data: 'two',
+            isStale: true,
+          },
+        ])
+
+        expect(states2).toMatchObject([
+          // First render, data is stale and starts fetching
+          {
+            data: 'prefetch',
+            isStale: true,
+          },
+          // Second createQuery data came in
+          {
+            data: 'two',
+            isStale: false,
+          },
+          // Data became stale after 10ms
+          {
+            data: 'two',
+            isStale: true,
+          },
+        ])
+      })()
+    },
+  )
+
+  it(
+    'should re-render when a query becomes stale',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<string>> = []
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => 'test',
+          staleTime: 50,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the query to become stale
+      await sleep(100)
+
+      expect(states.length).toBe(3)
+      expect(states[0]).toMatchObject({ isStale: true })
+      expect(states[1]).toMatchObject({ isStale: false })
+      expect(states[2]).toMatchObject({ isStale: true })
+    }),
+  )
+
+  it(
+    'should not re-render when it should only re-render on data changes and the data did not change',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<string>> = []
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => promise,
+          notifyOnChangeProps: ['data'],
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      resolve('test')
+
+      // Refetch the query
+      setTimeout(() => {
+        query.refetch()
+      }, 10)
+
+      await vi.waitFor(() => {
+        expect(states.length).toBe(2)
+      })
+
+      expect(states[0]).toMatchObject({
+        data: undefined,
+        status: 'pending',
+        isFetching: true,
+      })
+      expect(states[1]).toMatchObject({
+        data: 'test',
+        status: 'success',
+        isFetching: false,
+      })
+    }),
+  )
+
+  it(
+    'should track properties and only re-render when a tracked property changes',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<string | undefined> = []
+      const { promise, resolve } = promiseWithResolvers<string>()
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => promise,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push(query.data)
+      })
+
+      // Resolve the promise after a delay
+      setTimeout(() => {
+        resolve('test')
+      }, 10)
+
+      await vi.waitFor(() => expect(query.data).toBe('test'))
+
+      // Refetch after data is available
+      setTimeout(() => {
+        if (query.data) {
+          query.refetch()
+        }
+      }, 20)
+
+      // Wait for refetch to complete
+      await sleep(30)
+
+      expect(states.length).toBe(2)
+      expect(states[0]).toBe(undefined)
+      expect(states[1]).toBe('test')
+    }),
+  )
+
+  it(
+    'should always re-render if we are tracking props but not using any',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      let renderCount = 0
+      const states: Array<CreateQueryResult<string>> = []
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.resolve('test'),
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Track changes to the query state
+      $effect(() => {
+        // @ts-expect-error
+        const _ = { ...query }
+        renderCount++
+      })
+
+      await vi.waitFor(() => expect(query.data).toBe('test'))
+
+      expect(renderCount).toBe(2)
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined })
+      expect(states[1]).toMatchObject({ data: 'test' })
+    }),
+  )
+
+  it(
+    'should update query options',
+    withEffectRoot(() => {
+      const key = ['test-key']
+
+      const queryFn = async () => {
+        await sleep(10)
+        return 'data1'
+      }
+
+      // Create two queries with the same key but different options
+      createQuery(
+        () => ({ queryKey: key, queryFn, retryDelay: 10 }),
+        () => queryClient,
+      )
+
+      createQuery(
+        () => ({ queryKey: key, queryFn, retryDelay: 20 }),
+        () => queryClient,
+      )
+
+      // The last options should win
+      expect(queryCache.find({ queryKey: key })!.options.retryDelay).toBe(20)
+    }),
+  )
+
+  it(
+    'should start with status pending, fetchStatus idle if enabled is false',
+    withEffectRoot(async () => {
+      const key1 = ['test-key-1']
+      const key2 = ['test-key-2']
+      const states1: Array<CreateQueryResult<string>> = []
+      const states2: Array<CreateQueryResult<string>> = []
+
+      const query1 = createQuery<string>(
+        () => ({
+          queryKey: key1,
+          queryFn: () => 'data',
+          enabled: false,
+        }),
+        () => queryClient,
+      )
+
+      const query2 = createQuery<string>(
+        () => ({
+          queryKey: key2,
+          queryFn: () => 'data',
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states1.push({ ...query1 })
+      })
+
+      $effect(() => {
+        states2.push({ ...query2 })
+      })
+
+      // Check initial states
+      expect(query1.status).toBe('pending')
+      expect(query1.fetchStatus).toBe('idle')
+
+      // Wait for second query to complete
+      await vi.waitFor(() => {
+        expect(query2.status).toBe('success')
+        expect(query2.fetchStatus).toBe('idle')
+      })
+
+      // Verify the state transitions for the second query
+      expect(states2[0]?.status).toBe('pending')
+      expect(states2[0]?.fetchStatus).toBe('fetching')
+    }),
+  )
+
+  it(
+    'should be in "pending" state by default',
+    withEffectRoot(() => {
+      const key = ['test-key']
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => new Promise(() => {}),
+        }),
+        () => queryClient,
+      )
+
+      expect(query.status).toBe('pending')
+    }),
+  )
+
+  it(
+    'should not refetch query on focus when `enabled` is set to `false`',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const queryFn = vi.fn().mockReturnValue('data')
+
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn,
+          enabled: false,
+        }),
+        () => queryClient,
+      )
+
+      // Wait a bit to ensure the query has time to settle
+      await sleep(10)
+
+      // Simulate window focus
+      window.dispatchEvent(new Event('visibilitychange'))
+
+      // Wait a bit more to ensure no refetch happens
+      await sleep(10)
+
+      // The query function should not have been called
+      expect(queryFn).not.toHaveBeenCalled()
+
+      // Data should be undefined since the query is disabled
+      expect(query.data).toBeUndefined()
+    }),
+  )
+
+  it(
+    'should not refetch stale query on focus when `refetchOnWindowFocus` is set to `false`',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => count++,
+          staleTime: 0,
+          refetchOnWindowFocus: false,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the initial fetch to complete
+      await vi.waitFor(() => expect(query.data).toBe(0))
+
+      // Simulate window focus
+      window.dispatchEvent(new Event('visibilitychange'))
+
+      // Wait a bit to ensure no refetch happens
+      await sleep(10)
+
+      // Should only have 2 states: initial and after fetch
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined, isFetching: true })
+      expect(states[1]).toMatchObject({ data: 0, isFetching: false })
+
+      // Count should still be 0 since no refetch occurred
+      expect(count).toBe(1)
+    }),
+  )
+
+  it(
+    'should not refetch stale query on focus when `refetchOnWindowFocus` is set to a function that returns `false`',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => count++,
+          staleTime: 0,
+          refetchOnWindowFocus: () => false,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the initial fetch to complete
+      await vi.waitFor(() => expect(query.data).toBe(0))
+
+      // Simulate window focus
+      window.dispatchEvent(new Event('visibilitychange'))
+
+      // Wait a bit to ensure no refetch happens
+      await sleep(10)
+
+      // Should only have 2 states: initial and after fetch
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined, isFetching: true })
+      expect(states[1]).toMatchObject({ data: 0, isFetching: false })
+
+      // Count should still be 0 since no refetch occurred
+      expect(count).toBe(1)
+    }),
+  )
+
+  it(
+    'should not refetch fresh query on focus when `refetchOnWindowFocus` is set to `true`',
+    withEffectRoot(async () => {
+      const key = ['test-key']
+      const states: Array<CreateQueryResult<number>> = []
+      let count = 0
+
+      const query = createQuery<number>(
+        () => ({
+          queryKey: key,
+          queryFn: () => count++,
+          staleTime: Infinity,
+          refetchOnWindowFocus: true,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the initial fetch to complete
+      await vi.waitFor(() => expect(query.data).toBe(0))
+
+      // Simulate window focus
+      window.dispatchEvent(new Event('visibilitychange'))
+
+      // Wait a bit to ensure no refetch happens
+      await sleep(10)
+
+      // Should only have 2 states: initial and after fetch
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({ data: undefined, isFetching: true })
+      expect(states[1]).toMatchObject({ data: 0, isFetching: false })
+
+      // Count should still be 0 since no refetch occurred
+      expect(count).toBe(1)
+    }),
+  )
+
+  it('should refetch fresh query when refetchOnMount is set to always', async () => {
+    const key = ['test-key']
+    const states: Array<CreateQueryResult<string>> = []
+
+    // Prefetch the query
+    await queryClient.prefetchQuery({
+      queryKey: key,
+      queryFn: () => 'prefetched',
+    })
+
+    await withEffectRoot(async () => {
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => 'data',
+          refetchOnMount: 'always',
+          staleTime: Infinity,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the refetch to complete
+      await vi.waitFor(() => expect(query.data).toBe('data'))
+
+      // Should have 2 states: initial (with prefetched data) and after refetch
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({
+        data: 'prefetched',
+        isStale: false,
+        isFetching: true,
+      })
+      expect(states[1]).toMatchObject({
+        data: 'data',
+        isStale: false,
+        isFetching: false,
+      })
+    })()
+  })
+
+  it('should refetch stale query when refetchOnMount is set to true', async () => {
+    const key = ['test-key']
+    const states: Array<CreateQueryResult<string>> = []
+
+    // Prefetch the query
+    await queryClient.prefetchQuery({
+      queryKey: key,
+      queryFn: () => 'prefetched',
+    })
+
+    await withEffectRoot(async () => {
+      const query = createQuery<string>(
+        () => ({
+          queryKey: key,
+          queryFn: () => 'data',
+          refetchOnMount: true,
+          staleTime: 0,
+        }),
+        () => queryClient,
+      )
+
+      $effect(() => {
+        states.push({ ...query })
+      })
+
+      // Wait for the refetch to complete
+      await vi.waitFor(() => expect(query.data).toBe('data'))
+
+      // Should have 2 states: initial (with prefetched data) and after refetch
+      expect(states.length).toBe(2)
+      expect(states[0]).toMatchObject({
+        data: 'prefetched',
+        isStale: true,
+        isFetching: true,
+      })
+      expect(states[1]).toMatchObject({
+        data: 'data',
+        isStale: true,
+        isFetching: false,
+      })
+    })()
+  })
+
+  it(
+    'should set status to error if queryFn throws',
+    withEffectRoot(async () => {
+      const key = ['test-key'] // Declare key variable
+      const consoleMock = vi
+        .spyOn(console, 'error')
+        .mockImplementation(() => undefined)
+
+      const query = createQuery<string, Error>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.reject(new Error('Error test')),
+          retry: false,
+        }),
+        () => queryClient,
+      )
+
+      await vi.waitFor(() => expect(query.status).toBe('error'))
+      expect(query.error?.message).toBe('Error test')
+
+      consoleMock.mockRestore()
+    }),
+  )
+
+  it(
+    'should set status to error instead of throwing when error should not be thrown',
+    withEffectRoot(async () => {
+      const key = ['test-key'] // Declare key variable
+
+      const query = createQuery<string, Error>(
+        () => ({
+          queryKey: key,
+          queryFn: () => Promise.reject(new Error('Local Error')),
+          retry: false,
+          throwOnError: (err) => err.message !== 'Local Error',
+        }),
+        () => queryClient,
+      )
+
+      await vi.waitFor(() => expect(query.status).toBe('error'))
+      expect(query.error?.message).toBe('Local Error')
+    }),
+  )
+})
diff --git a/packages/svelte-query/tests/createQuery.test-d.ts b/packages/svelte-query/tests/createQuery.test-d.ts
new file mode 100644
index 0000000000..5ede74c49d
--- /dev/null
+++ b/packages/svelte-query/tests/createQuery.test-d.ts
@@ -0,0 +1,88 @@
+import { describe, expectTypeOf, it } from 'vitest'
+import { createQuery, queryOptions } from '../src/index.js'
+
+describe('initialData', () => {
+  describe('Config object overload', () => {
+    it('TData should always be defined when initialData is provided as an object', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+        initialData: { wow: true },
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
+    })
+
+    it('TData should be defined when passed through queryOptions', () => {
+      const options = queryOptions({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+        initialData: { wow: true },
+      })
+      const { data } = createQuery(() => options)
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
+    })
+
+    it('TData should have undefined in the union when initialData is NOT provided', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
+    })
+
+    it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+        initialData: () => undefined as { wow: boolean } | undefined,
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
+    })
+  })
+
+  describe('Query key overload', () => {
+    it('TData should always be defined when initialData is provided', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+        initialData: { wow: true },
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
+    })
+
+    it('TData should have undefined in the union when initialData is NOT provided', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
+    })
+  })
+
+  describe('Query key and func', () => {
+    it('TData should always be defined when initialData is provided', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+        initialData: { wow: true },
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
+    })
+
+    it('TData should have undefined in the union when initialData is NOT provided', () => {
+      const { data } = createQuery(() => ({
+        queryKey: ['key'],
+        queryFn: () => ({ wow: true }),
+      }))
+
+      expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
+    })
+  })
+})
diff --git a/packages/svelte-query/tests/createQuery/BaseExample.svelte b/packages/svelte-query/tests/createQuery/BaseExample.svelte
deleted file mode 100644
index d7a824c26b..0000000000
--- a/packages/svelte-query/tests/createQuery/BaseExample.svelte
+++ /dev/null
@@ -1,18 +0,0 @@
-<script lang="ts">
-  import { createQuery } from '../../src/index.js'
-  import type { QueryClient, QueryObserverResult } from '@tanstack/query-core'
-  import type { Writable } from 'svelte/store'
-  import type { CreateQueryOptions, StoreOrVal } from '../../src/index.js'
-
-  export let options: StoreOrVal<CreateQueryOptions<any>>
-  export let queryClient: QueryClient
-  export let states: Writable<Array<QueryObserverResult>>
-
-  const query = createQuery(options, queryClient)
-
-  $: states.update((prev) => [...prev, $query])
-</script>
-
-<div>Status: {$query.status}</div>
-<div>Failure Count: {$query.failureCount}</div>
-<div>Data: {$query.data ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/createQuery/DisabledExample.svelte b/packages/svelte-query/tests/createQuery/DisabledExample.svelte
deleted file mode 100644
index 517a4813af..0000000000
--- a/packages/svelte-query/tests/createQuery/DisabledExample.svelte
+++ /dev/null
@@ -1,31 +0,0 @@
-<script lang="ts">
-  import { QueryClient } from '@tanstack/query-core'
-  import { derived, writable } from 'svelte/store'
-  import { createQuery } from '../../src/index.js'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { QueryObserverResult } from '@tanstack/query-core'
-  import type { Writable } from 'svelte/store'
-
-  export let states: Writable<Array<QueryObserverResult>>
-
-  const queryClient = new QueryClient()
-  const count = writable(0)
-
-  const options = derived(count, ($count) => ({
-    queryKey: ['test', $count],
-    queryFn: async () => {
-      await sleep(5)
-      return $count
-    },
-    enabled: $count === 0,
-  }))
-
-  const query = createQuery(options, queryClient)
-
-  $: states.update((prev) => [...prev, $query])
-</script>
-
-<button on:click={() => ($count += 1)}>Increment</button>
-
-<div>Data: {$query.data ?? 'undefined'}</div>
-<div>Count: {$count}</div>
diff --git a/packages/svelte-query/tests/createQuery/PlaceholderData.svelte b/packages/svelte-query/tests/createQuery/PlaceholderData.svelte
deleted file mode 100644
index 587861ccab..0000000000
--- a/packages/svelte-query/tests/createQuery/PlaceholderData.svelte
+++ /dev/null
@@ -1,30 +0,0 @@
-<script lang="ts">
-  import { derived, writable } from 'svelte/store'
-  import { createQuery, keepPreviousData } from '../../src/index.js'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { QueryClient, QueryObserverResult } from '@tanstack/query-core'
-  import type { Writable } from 'svelte/store'
-
-  export let queryClient: QueryClient
-  export let states: Writable<Array<QueryObserverResult>>
-
-  const count = writable(0)
-
-  const options = derived(count, ($count) => ({
-    queryKey: ['test', $count],
-    queryFn: async () => {
-      await sleep(5)
-      return $count
-    },
-    placeholderData: keepPreviousData,
-  }))
-
-  const query = createQuery(options, queryClient)
-
-  $: states.update((prev) => [...prev, $query])
-</script>
-
-<button on:click={() => ($count += 1)}>setCount</button>
-
-<div>Status: {$query.status}</div>
-<div>Data: {$query.data ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/createQuery/RefetchExample.svelte b/packages/svelte-query/tests/createQuery/RefetchExample.svelte
deleted file mode 100644
index ae37ed14c0..0000000000
--- a/packages/svelte-query/tests/createQuery/RefetchExample.svelte
+++ /dev/null
@@ -1,32 +0,0 @@
-<script lang="ts">
-  import { QueryClient } from '@tanstack/query-core'
-  import { derived, writable } from 'svelte/store'
-  import { createQuery } from '../../src/index.js'
-  import { sleep } from '@tanstack/query-test-utils'
-  import type { QueryObserverResult } from '@tanstack/query-core'
-  import type { Writable } from 'svelte/store'
-
-  export let states: Writable<Array<QueryObserverResult>>
-
-  const queryClient = new QueryClient()
-  const count = writable(0)
-
-  const options = derived(count, ($count) => ({
-    queryKey: ['test'],
-    queryFn: async () => {
-      await sleep(5)
-      return ++$count
-    },
-  }))
-
-  const query = createQuery(options, queryClient)
-
-  $: states.update((prev) => [...prev, $query])
-</script>
-
-<button on:click={() => queryClient.removeQueries({ queryKey: ['test'] })}
-  >Remove</button
->
-<button on:click={() => $query.refetch()}>Refetch</button>
-
-<div>Data: {$query.data ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/createQuery/createQuery.test-d.ts b/packages/svelte-query/tests/createQuery/createQuery.test-d.ts
deleted file mode 100644
index 7936758401..0000000000
--- a/packages/svelte-query/tests/createQuery/createQuery.test-d.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { describe, expectTypeOf, test } from 'vitest'
-import { get } from 'svelte/store'
-import { createQuery, queryOptions } from '../../src/index.js'
-import type { OmitKeyof } from '@tanstack/query-core'
-import type { CreateQueryOptions } from '../../src/index.js'
-
-describe('createQuery', () => {
-  test('TData should always be defined when initialData is provided as an object', () => {
-    const query = createQuery({
-      queryKey: ['key'],
-      queryFn: () => ({ wow: true }),
-      initialData: { wow: true },
-    })
-
-    expectTypeOf(get(query).data).toEqualTypeOf<{ wow: boolean }>()
-  })
-
-  test('TData should be defined when passed through queryOptions', () => {
-    const options = queryOptions({
-      queryKey: ['key'],
-      queryFn: () => ({ wow: true }),
-      initialData: { wow: true },
-    })
-    const query = createQuery(options)
-
-    expectTypeOf(get(query).data).toEqualTypeOf<{ wow: boolean }>()
-  })
-
-  test('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {
-    const query = createQuery({
-      queryKey: ['key'],
-      queryFn: () => ({ wow: true }),
-      initialData: () => ({ wow: true }),
-    })
-
-    expectTypeOf(get(query).data).toEqualTypeOf<{ wow: boolean }>()
-  })
-
-  test('TData should have undefined in the union when initialData is NOT provided', () => {
-    const query = createQuery({
-      queryKey: ['key'],
-      queryFn: () => {
-        return {
-          wow: true,
-        }
-      },
-    })
-
-    expectTypeOf(get(query).data).toEqualTypeOf<{ wow: boolean } | undefined>()
-  })
-
-  test('Allow custom hooks using CreateQueryOptions', () => {
-    type Data = string
-
-    const useCustomQuery = (
-      options?: OmitKeyof<CreateQueryOptions<Data>, 'queryKey' | 'queryFn'>,
-    ) => {
-      return createQuery({
-        ...options,
-        queryKey: ['todos-key'],
-        queryFn: () => Promise.resolve('data'),
-      })
-    }
-
-    const query = useCustomQuery()
-
-    expectTypeOf(get(query).data).toEqualTypeOf<Data | undefined>()
-  })
-})
diff --git a/packages/svelte-query/tests/createQuery/createQuery.test.ts b/packages/svelte-query/tests/createQuery/createQuery.test.ts
deleted file mode 100644
index f2fc002516..0000000000
--- a/packages/svelte-query/tests/createQuery/createQuery.test.ts
+++ /dev/null
@@ -1,421 +0,0 @@
-import { describe, expect, test } from 'vitest'
-import { fireEvent, render, waitFor } from '@testing-library/svelte'
-import { derived, get, writable } from 'svelte/store'
-import { QueryClient } from '@tanstack/query-core'
-import { sleep } from '@tanstack/query-test-utils'
-import BaseExample from './BaseExample.svelte'
-import DisabledExample from './DisabledExample.svelte'
-import PlaceholderData from './PlaceholderData.svelte'
-import RefetchExample from './RefetchExample.svelte'
-import type { Writable } from 'svelte/store'
-import type { QueryObserverResult } from '@tanstack/query-core'
-
-describe('createQuery', () => {
-  test('Return the correct states for a successful query', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const options = {
-      queryKey: ['test'],
-      queryFn: async () => {
-        await sleep(5)
-        return 'Success'
-      },
-    }
-
-    const rendered = render(BaseExample, {
-      props: {
-        options,
-        queryClient: new QueryClient(),
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => {
-      expect(rendered.queryByText('Status: success')).toBeInTheDocument()
-    })
-
-    const states = get(statesStore)
-
-    expect(states).toHaveLength(2)
-
-    expect(states[0]).toMatchObject({
-      data: undefined,
-      dataUpdatedAt: 0,
-      error: null,
-      errorUpdatedAt: 0,
-      failureCount: 0,
-      failureReason: null,
-      errorUpdateCount: 0,
-      isError: false,
-      isFetched: false,
-      isFetchedAfterMount: false,
-      isFetching: true,
-      isPaused: false,
-      isPending: true,
-      isInitialLoading: true,
-      isLoading: true,
-      isLoadingError: false,
-      isPlaceholderData: false,
-      isRefetchError: false,
-      isRefetching: false,
-      isStale: true,
-      isSuccess: false,
-      refetch: expect.any(Function),
-      status: 'pending',
-      fetchStatus: 'fetching',
-    })
-
-    expect(states[1]).toMatchObject({
-      data: 'Success',
-      dataUpdatedAt: expect.any(Number),
-      error: null,
-      errorUpdatedAt: 0,
-      failureCount: 0,
-      failureReason: null,
-      errorUpdateCount: 0,
-      isError: false,
-      isFetched: true,
-      isFetchedAfterMount: true,
-      isFetching: false,
-      isPaused: false,
-      isPending: false,
-      isInitialLoading: false,
-      isLoading: false,
-      isLoadingError: false,
-      isPlaceholderData: false,
-      isRefetchError: false,
-      isRefetching: false,
-      isStale: true,
-      isSuccess: true,
-      refetch: expect.any(Function),
-      status: 'success',
-      fetchStatus: 'idle',
-    })
-  })
-
-  test('Return the correct states for an unsuccessful query', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const options = {
-      queryKey: ['test'],
-      queryFn: async () => Promise.reject(new Error('Rejected')),
-      retry: 1,
-      retryDelay: 1,
-    }
-
-    const rendered = render(BaseExample, {
-      props: {
-        options,
-        queryClient: new QueryClient(),
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => rendered.getByText('Status: error'))
-
-    const states = get(statesStore)
-
-    expect(states).toHaveLength(3)
-
-    expect(states[0]).toMatchObject({
-      data: undefined,
-      dataUpdatedAt: 0,
-      error: null,
-      errorUpdatedAt: 0,
-      failureCount: 0,
-      failureReason: null,
-      errorUpdateCount: 0,
-      isError: false,
-      isFetched: false,
-      isFetchedAfterMount: false,
-      isFetching: true,
-      isPaused: false,
-      isPending: true,
-      isInitialLoading: true,
-      isLoading: true,
-      isLoadingError: false,
-      isPlaceholderData: false,
-      isRefetchError: false,
-      isRefetching: false,
-      isStale: true,
-      isSuccess: false,
-      refetch: expect.any(Function),
-      status: 'pending',
-      fetchStatus: 'fetching',
-    })
-
-    expect(states[1]).toMatchObject({
-      data: undefined,
-      dataUpdatedAt: 0,
-      error: null,
-      errorUpdatedAt: 0,
-      failureCount: 1,
-      failureReason: new Error('Rejected'),
-      errorUpdateCount: 0,
-      isError: false,
-      isFetched: false,
-      isFetchedAfterMount: false,
-      isFetching: true,
-      isPaused: false,
-      isPending: true,
-      isInitialLoading: true,
-      isLoading: true,
-      isLoadingError: false,
-      isPlaceholderData: false,
-      isRefetchError: false,
-      isRefetching: false,
-      isStale: true,
-      isSuccess: false,
-      refetch: expect.any(Function),
-      status: 'pending',
-      fetchStatus: 'fetching',
-    })
-
-    expect(states[2]).toMatchObject({
-      data: undefined,
-      dataUpdatedAt: 0,
-      error: new Error('Rejected'),
-      errorUpdatedAt: expect.any(Number),
-      failureCount: 2,
-      failureReason: new Error('Rejected'),
-      errorUpdateCount: 1,
-      isError: true,
-      isFetched: true,
-      isFetchedAfterMount: true,
-      isFetching: false,
-      isPaused: false,
-      isPending: false,
-      isInitialLoading: false,
-      isLoading: false,
-      isLoadingError: true,
-      isPlaceholderData: false,
-      isRefetchError: false,
-      isRefetching: false,
-      isStale: true,
-      isSuccess: false,
-      refetch: expect.any(Function),
-      status: 'error',
-      fetchStatus: 'idle',
-    })
-  })
-
-  test('Accept a writable store for options', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const optionsStore = writable({
-      queryKey: ['test'],
-      queryFn: async () => {
-        await sleep(5)
-        return 'Success'
-      },
-    })
-
-    const rendered = render(BaseExample, {
-      props: {
-        options: optionsStore,
-        queryClient: new QueryClient(),
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => {
-      expect(rendered.queryByText('Status: success')).toBeInTheDocument()
-    })
-  })
-
-  test('Accept a derived store for options', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const writableStore = writable('test')
-
-    const derivedStore = derived(writableStore, ($store) => ({
-      queryKey: [$store],
-      queryFn: async () => {
-        await sleep(5)
-        return 'Success'
-      },
-    }))
-
-    const rendered = render(BaseExample, {
-      props: {
-        options: derivedStore,
-        queryClient: new QueryClient(),
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => {
-      expect(rendered.queryByText('Status: success')).toBeInTheDocument()
-    })
-  })
-
-  test('Ensure reactivity when queryClient defaults are set', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const writableStore = writable(1)
-
-    const derivedStore = derived(writableStore, ($store) => ({
-      queryKey: [$store],
-      queryFn: async () => {
-        await sleep(5)
-        return $store
-      },
-    }))
-
-    const rendered = render(BaseExample, {
-      props: {
-        options: derivedStore,
-        queryClient: new QueryClient({
-          defaultOptions: { queries: { staleTime: 60 * 1000 } },
-        }),
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => {
-      expect(rendered.queryByText('Data: 1')).toBeInTheDocument()
-      expect(rendered.queryByText('Data: 2')).not.toBeInTheDocument()
-    })
-
-    writableStore.set(2)
-
-    await waitFor(() => {
-      expect(rendered.queryByText('Data: 1')).not.toBeInTheDocument()
-      expect(rendered.queryByText('Data: 2')).toBeInTheDocument()
-    })
-
-    writableStore.set(1)
-
-    await waitFor(() => {
-      expect(rendered.queryByText('Data: 1')).toBeInTheDocument()
-      expect(rendered.queryByText('Data: 2')).not.toBeInTheDocument()
-    })
-  })
-
-  test('Keep previous data when placeholderData is set', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const rendered = render(PlaceholderData, {
-      props: {
-        queryClient: new QueryClient(),
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => rendered.getByText('Data: 0'))
-
-    fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
-
-    await waitFor(() => rendered.getByText('Data: 1'))
-
-    const states = get(statesStore)
-
-    expect(states).toHaveLength(4)
-
-    // Initial
-    expect(states[0]).toMatchObject({
-      data: undefined,
-      isFetching: true,
-      isSuccess: false,
-      isPlaceholderData: false,
-    })
-
-    // Fetched
-    expect(states[1]).toMatchObject({
-      data: 0,
-      isFetching: false,
-      isSuccess: true,
-      isPlaceholderData: false,
-    })
-
-    // Set state
-    expect(states[2]).toMatchObject({
-      data: 0,
-      isFetching: true,
-      isSuccess: true,
-      isPlaceholderData: true,
-    })
-
-    // New data
-    expect(states[3]).toMatchObject({
-      data: 1,
-      isFetching: false,
-      isSuccess: true,
-      isPlaceholderData: false,
-    })
-  })
-
-  test('Should not fetch when switching to a disabled query', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const rendered = render(DisabledExample, {
-      props: {
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => rendered.getByText('Data: 0'))
-
-    fireEvent.click(rendered.getByRole('button', { name: /Increment/i }))
-
-    await waitFor(() => {
-      rendered.getByText('Count: 1')
-      rendered.getByText('Data: undefined')
-    })
-
-    const states = get(statesStore)
-
-    expect(states).toHaveLength(3)
-
-    // Fetch query
-    expect(states[0]).toMatchObject({
-      data: undefined,
-      isFetching: true,
-      isSuccess: false,
-    })
-
-    // Fetched query
-    expect(states[1]).toMatchObject({
-      data: 0,
-      isFetching: false,
-      isSuccess: true,
-    })
-
-    // Switch to disabled query
-    expect(states[2]).toMatchObject({
-      data: undefined,
-      isFetching: false,
-      isSuccess: false,
-    })
-  })
-
-  test('Create a new query when refetching a removed query', async () => {
-    const statesStore: Writable<Array<QueryObserverResult>> = writable([])
-
-    const rendered = render(RefetchExample, {
-      props: {
-        states: statesStore,
-      },
-    })
-
-    await waitFor(() => rendered.getByText('Data: 1'))
-    fireEvent.click(rendered.getByRole('button', { name: /Remove/i }))
-
-    await sleep(5)
-
-    fireEvent.click(rendered.getByRole('button', { name: /Refetch/i }))
-    await waitFor(() => rendered.getByText('Data: 2'))
-
-    const states = get(statesStore)
-
-    expect(states.length).toBe(4)
-    // Initial
-    expect(states[0]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })
-    // Fetched
-    expect(states[1]).toMatchObject({ data: 1 })
-    // Switch
-    expect(states[2]).toMatchObject({ data: undefined, dataUpdatedAt: 0 })
-    // Fetched
-    expect(states[3]).toMatchObject({ data: 2 })
-  })
-})
diff --git a/packages/svelte-query/tests/infiniteQueryOptions/infiniteQueryOptions.test-d.ts b/packages/svelte-query/tests/infiniteQueryOptions/infiniteQueryOptions.test-d.ts
index 45f98dd085..8cec61e6ea 100644
--- a/packages/svelte-query/tests/infiniteQueryOptions/infiniteQueryOptions.test-d.ts
+++ b/packages/svelte-query/tests/infiniteQueryOptions/infiniteQueryOptions.test-d.ts
@@ -1,5 +1,4 @@
 import { describe, expectTypeOf, test } from 'vitest'
-import { get } from 'svelte/store'
 import { QueryClient } from '@tanstack/query-core'
 import { createInfiniteQuery, infiniteQueryOptions } from '../../src/index.js'
 import type { InfiniteData } from '@tanstack/query-core'
@@ -37,10 +36,10 @@ describe('queryOptions', () => {
       initialPageParam: 1,
     })
 
-    const query = createInfiniteQuery(options)
+    const query = createInfiniteQuery(() => options)
 
     // known issue: type of pageParams is unknown when returned from useInfiniteQuery
-    expectTypeOf(get(query).data).toEqualTypeOf<
+    expectTypeOf(query.data).toEqualTypeOf<
       InfiniteData<string, unknown> | undefined
     >()
   })
diff --git a/packages/svelte-query/tests/queryOptions/queryOptions.test-d.ts b/packages/svelte-query/tests/queryOptions/queryOptions.test-d.ts
index 8562a7c227..1dc175f61e 100644
--- a/packages/svelte-query/tests/queryOptions/queryOptions.test-d.ts
+++ b/packages/svelte-query/tests/queryOptions/queryOptions.test-d.ts
@@ -1,5 +1,4 @@
 import { describe, expectTypeOf, test } from 'vitest'
-import { get } from 'svelte/store'
 import {
   QueriesObserver,
   QueryClient,
@@ -46,11 +45,11 @@ describe('queryOptions', () => {
       queryFn: () => Promise.resolve(5),
     })
 
-    const queries = createQueries({
+    const queries = createQueries(() => ({
       queries: [options],
-    })
+    }))
 
-    expectTypeOf(get(queries)[0].data).toEqualTypeOf<number | undefined>()
+    expectTypeOf(queries[0].data).toEqualTypeOf<number | undefined>()
   })
 
   test('Should tag the queryKey with the result type of the QueryFn', () => {
diff --git a/packages/svelte-query/tests/useIsFetching/BaseExample.svelte b/packages/svelte-query/tests/useIsFetching/BaseExample.svelte
index 16f13a808d..03af7fa890 100644
--- a/packages/svelte-query/tests/useIsFetching/BaseExample.svelte
+++ b/packages/svelte-query/tests/useIsFetching/BaseExample.svelte
@@ -1,27 +1,27 @@
 <script lang="ts">
   import { QueryClient } from '@tanstack/query-core'
-  import { derived, writable } from 'svelte/store'
   import { createQuery, useIsFetching } from '../../src/index.js'
   import { sleep } from '@tanstack/query-test-utils'
 
   const queryClient = new QueryClient()
-  const ready = writable(false)
+  let ready = $state(false)
 
   const isFetching = useIsFetching(undefined, queryClient)
 
-  const options = derived(ready, ($ready) => ({
-    queryKey: ['test'],
-    queryFn: async () => {
-      await sleep(5)
-      return 'test'
-    },
-    enabled: $ready,
-  }))
-
-  const query = createQuery(options, queryClient)
+  const query = createQuery(
+    () => ({
+      queryKey: ['test'],
+      queryFn: async () => {
+        await sleep(5)
+        return 'test'
+      },
+      enabled: ready,
+    }),
+    () => queryClient,
+  )
 </script>
 
-<button on:click={() => ($ready = true)}>setReady</button>
+<button onclick={() => (ready = true)}>setReady</button>
 
-<div>isFetching: {$isFetching}</div>
-<div>Data: {$query.data ?? 'undefined'}</div>
+<div>isFetching: {isFetching.current}</div>
+<div>Data: {query.data ?? 'undefined'}</div>
diff --git a/packages/svelte-query/tests/useIsFetching/useIsFetching.test.ts b/packages/svelte-query/tests/useIsFetching/useIsFetching.svelte.test.ts
similarity index 64%
rename from packages/svelte-query/tests/useIsFetching/useIsFetching.test.ts
rename to packages/svelte-query/tests/useIsFetching/useIsFetching.svelte.test.ts
index 7ca6ca6322..6420dfdfd3 100644
--- a/packages/svelte-query/tests/useIsFetching/useIsFetching.test.ts
+++ b/packages/svelte-query/tests/useIsFetching/useIsFetching.svelte.test.ts
@@ -1,5 +1,5 @@
 import { describe, test } from 'vitest'
-import { fireEvent, render } from '@testing-library/svelte'
+import { fireEvent, render, waitFor } from '@testing-library/svelte'
 import BaseExample from './BaseExample.svelte'
 
 describe('useIsFetching', () => {
@@ -8,7 +8,10 @@ describe('useIsFetching', () => {
 
     await rendered.findByText('isFetching: 0')
     fireEvent.click(rendered.getByRole('button', { name: /setReady/i }))
-    await rendered.findByText('isFetching: 1')
-    await rendered.findByText('isFetching: 0')
+
+    waitFor(async () => {
+      await rendered.findByText('isFetching: 1')
+      await rendered.findByText('isFetching: 0')
+    })
   })
 })
diff --git a/packages/svelte-query/tests/useIsMutating/BaseExample.svelte b/packages/svelte-query/tests/useIsMutating/BaseExample.svelte
index 43df62a36a..b453411cf6 100644
--- a/packages/svelte-query/tests/useIsMutating/BaseExample.svelte
+++ b/packages/svelte-query/tests/useIsMutating/BaseExample.svelte
@@ -7,17 +7,17 @@
   const isMutating = useIsMutating(undefined, queryClient)
 
   const mutation = createMutation(
-    {
+    () => ({
       mutationKey: ['mutation-1'],
       mutationFn: async () => {
         await sleep(5)
         return 'data'
       },
-    },
-    queryClient,
+    }),
+    () => queryClient,
   )
 </script>
 
-<button on:click={() => $mutation.mutate()}>Trigger</button>
+<button onclick={() => mutation.mutate()}>Trigger</button>
 
-<div>isMutating: {$isMutating}</div>
+<div>isMutating: {isMutating.current}</div>
diff --git a/packages/svelte-query/tests/useIsMutating/useIsMutating.test.ts b/packages/svelte-query/tests/useIsMutating/useIsMutating.svelte.test.ts
similarity index 100%
rename from packages/svelte-query/tests/useIsMutating/useIsMutating.test.ts
rename to packages/svelte-query/tests/useIsMutating/useIsMutating.svelte.test.ts
diff --git a/packages/svelte-query/tests/useMutationState/BaseExample.svelte b/packages/svelte-query/tests/useMutationState/BaseExample.svelte
index ce85130099..535485473b 100644
--- a/packages/svelte-query/tests/useMutationState/BaseExample.svelte
+++ b/packages/svelte-query/tests/useMutationState/BaseExample.svelte
@@ -6,13 +6,20 @@
     useMutationState,
   } from '../../src/index.js'
   import type {
+    Accessor,
     CreateMutationOptions,
     MutationStateOptions,
-  } from '../../src/types.js'
+  } from '../../src/index.js'
 
-  export let successMutationOpts: CreateMutationOptions
-  export let errorMutationOpts: CreateMutationOptions
-  export let mutationStateOpts: MutationStateOptions | undefined = undefined
+  let {
+    successMutationOpts,
+    errorMutationOpts,
+    mutationStateOpts,
+  }: {
+    successMutationOpts: Accessor<CreateMutationOptions>
+    errorMutationOpts: Accessor<CreateMutationOptions>
+    mutationStateOpts?: MutationStateOptions | undefined
+  } = $props()
 
   const queryClient = new QueryClient()
   setQueryClientContext(queryClient)
@@ -21,16 +28,16 @@
   const errorMutation = createMutation(errorMutationOpts)
 
   const mutationState = useMutationState(mutationStateOpts)
-  $: statuses = $mutationState.map((state) => state.status)
+  let statuses = $derived(mutationState.map((state) => state.status))
 </script>
 
 <div data-testid="result">
   {JSON.stringify(statuses)}
 </div>
 
-<button data-testid="success" on:click={() => $successMutation.mutate()}>
+<button data-testid="success" onclick={() => successMutation.mutate()}>
   Click
 </button>
-<button data-testid="error" on:click={() => $errorMutation.mutate()}>
+<button data-testid="error" onclick={() => errorMutation.mutate()}>
   Click
 </button>
diff --git a/packages/svelte-query/tests/useMutationState/useMutationState.test.ts b/packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts
similarity index 91%
rename from packages/svelte-query/tests/useMutationState/useMutationState.test.ts
rename to packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts
index 24bc261cc9..98cec47cbf 100644
--- a/packages/svelte-query/tests/useMutationState/useMutationState.test.ts
+++ b/packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts
@@ -12,15 +12,15 @@ describe('useMutationState', () => {
 
     const rendered = render(BaseExample, {
       props: {
-        successMutationOpts: {
+        successMutationOpts: () => ({
           mutationKey: ['success'],
           mutationFn: successMutationFn,
-        },
+        }),
 
-        errorMutationOpts: {
+        errorMutationOpts: () => ({
           mutationKey: ['error'],
           mutationFn: errorMutationFn,
-        },
+        }),
       },
     })
 
@@ -49,15 +49,15 @@ describe('useMutationState', () => {
 
     const rendered = render(BaseExample, {
       props: {
-        successMutationOpts: {
+        successMutationOpts: () => ({
           mutationKey: ['success'],
           mutationFn: successMutationFn,
-        },
+        }),
 
-        errorMutationOpts: {
+        errorMutationOpts: () => ({
           mutationKey: ['error'],
           mutationFn: errorMutationFn,
-        },
+        }),
 
         mutationStateOpts: {
           filters: { status: 'error' },
@@ -88,15 +88,15 @@ describe('useMutationState', () => {
 
     const rendered = render(BaseExample, {
       props: {
-        successMutationOpts: {
+        successMutationOpts: () => ({
           mutationKey: ['success'],
           mutationFn: successMutationFn,
-        },
+        }),
 
-        errorMutationOpts: {
+        errorMutationOpts: () => ({
           mutationKey: ['error'],
           mutationFn: errorMutationFn,
-        },
+        }),
 
         mutationStateOpts: {
           filters: { mutationKey: ['success'] },
diff --git a/packages/svelte-query/tests/utils.svelte.ts b/packages/svelte-query/tests/utils.svelte.ts
new file mode 100644
index 0000000000..b573a6edcc
--- /dev/null
+++ b/packages/svelte-query/tests/utils.svelte.ts
@@ -0,0 +1,33 @@
+export function ref<T>(initial: T) {
+  let value = $state(initial)
+
+  return {
+    get value() {
+      return value
+    },
+    set value(newValue) {
+      value = newValue
+    },
+  }
+}
+
+export function promiseWithResolvers<T>() {
+  let resolve: (value: T) => void
+  let reject: (reason?: any) => void
+  const promise = new Promise<T>((res, rej) => {
+    resolve = res
+    reject = rej
+  })
+  return { promise, resolve: resolve!, reject: reject! }
+}
+
+export function withEffectRoot(fn: () => void | Promise<void>) {
+  return async () => {
+    let promise: void | Promise<void> = Promise.resolve()
+    const cleanup = $effect.root(() => {
+      promise = fn()
+    })
+    await promise
+    cleanup()
+  }
+}
diff --git a/packages/svelte-query/vite.config.ts b/packages/svelte-query/vite.config.ts
index 1249fcc5a8..1ed8e56135 100644
--- a/packages/svelte-query/vite.config.ts
+++ b/packages/svelte-query/vite.config.ts
@@ -23,8 +23,7 @@ export default defineConfig({
     watch: false,
     environment: 'jsdom',
     setupFiles: ['./tests/test-setup.ts'],
-    coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] },
+    coverage: { enabled: false, provider: 'istanbul', include: ['src/**/*'] },
     typecheck: { enabled: true },
-    restoreMocks: true,
   },
 })
