SvelteKit Remote Functions
Current Status
Remote functions are experimental in SvelteKit 2.58. Enable them in
svelte.config.js:
jsexport default { kit: { experimental: { remoteFunctions: true } }, compilerOptions: { experimental: { async: true } } // only for await in components };
Quick Start
File naming: export remote functions from *.remote.ts or *.remote.js.
Remote files can live anywhere under src except src/lib/server.
Which function?
- Dynamic reads →
query() - Progressive forms →
form() - Event-handler mutations →
command() - Build-time/static reads →
prerender()
Example
ts// posts.remote.ts import { command, query, requested } from '$app/server'; import * as v from 'valibot'; export const getPosts = query(v.object({ tag: v.optional(v.string()) }), async (filter) => { return db.posts.find(filter); }); export const createPost = command(v.object({ title: v.string() }), async (data) => { await db.posts.create(data); for (const { query } of requested(getPosts, 5)) { void query.refresh(); } });
Client:
svelte<script lang="ts"> import { createPost, getPosts } from './posts.remote'; const posts = $derived(await getPosts({ tag: 'svelte' })); </script> <button onclick={() => createPost({ title: 'New' }).updates(getPosts)}> Create </button>
Current Rules
- Remote functions always run on the server, even when called from the browser.
- Args/returns use
devalue; avoid functions, class instances, symbols, circular refs, andRegExp. - Validate exposed inputs with Standard Schema (
valibot,zod,arktype, etc.) or use.unchecked/'unchecked'deliberately. query.batch()batches calls from the same macrotask to solve n+1 reads.form().enhance()submit()returnstruewhen submission is valid/successful andfalsefor validation failures..updates()is client-requested; server handlers must opt in withrequested(queryFn, limit).requested()now yields{ arg, query }; callquery.refresh()/query.set(...)on the bound instance.limitis required forrequested()to cap client-controlled refresh requests.- Inside command/form handlers, use
void query.refresh()/void query.set(value); SvelteKit awaits and serializes the updates. - Prefer
form()overcommand()where progressive enhancement matters. - Use
prerender()for data that changes at most once per deployment. - Last verified: SvelteKit 2.58.0, 2026-04-24
Reference Files
- references/remote-functions.md - Current patterns, examples, and gotchas

