SvelteKit Remote Functions: The End of tRPC Boilerplate?
SvelteKit's experimental remote functions give you type-safe server calls without routers, schemas, or middleware. Here's what they replace — and what they don't.
For years, the SvelteKit answer to “how do I call server code from the client with type safety?” was: use tRPC, write a bunch of router definitions, set up an adapter, and hope the types flow through. Or — the more SvelteKit-native answer — use form actions and load functions, which are great until you need something that doesn’t fit the page-based model.
Remote functions change this. They’re SvelteKit’s native solution for type-safe client-to-server communication, and they eliminate an entire category of boilerplate. But they’re also experimental, opinionated, and not a universal replacement for everything. Let’s be precise about what they are and aren’t.
What remote functions actually do
A remote function is a server-side function that you import and call from client code. The compiler handles the HTTP boundary — you write a function, call it like a function, and get full TypeScript inference across the gap.
Available since SvelteKit 2.27, remote functions compile your server-side code into HTTP endpoints and generate typed fetch wrappers automatically. You never write an API route, define a schema, or maintain a router.
Four function types:
query— fetch data. The most common type. Supports batching to solve n+1 problems.form— handle form submissions with progressive enhancement. Works without JavaScript.command— mutations triggered by JavaScript (button clicks, drag-and-drop, anything not a form). Requires JS.prerender— fetch data at build time and cache it. For static content that doesn’t change per-request.
The setup
Remote functions are experimental. You opt in via svelte.config.js:
export default {
compilerOptions: {
experimental: {
async: true
}
},
kit: {
experimental: {
remoteFunctions: true
}
}
};
Then you write a function in a .server.ts file and import it in your component:
// src/lib/server/todos.ts
import { query, command } from '$app/server';
import { db } from '$lib/server/db';
export const getTodos = query(async () => {
return db.select().from(todos);
});
export const addTodo = command(async (text: string) => {
return db.insert(todos).values({ text });
});
<!-- src/routes/todos/+page.svelte -->
<script>
import { getTodos, addTodo } from '$lib/server/todos';
let todos = getTodos();
</script>
That’s it. No router. No adapter. No schema definition. TypeScript knows the return type of getTodos and the argument type of addTodo because they’re the same function — the compiler just splits it across the network boundary.
What this replaces
tRPC: The most obvious comparison. tRPC requires defining a router, creating procedures with input validation (usually Zod), setting up a SvelteKit adapter, and configuring a client. Remote functions give you the same type safety with none of that infrastructure. For SvelteKit-only projects, it’s strictly less code.
Manual +server.ts API routes: If you’ve been writing GET and POST handlers in +server.ts files and manually typing the request/response, remote functions eliminate that entirely for internal communication.
Form actions for non-form things: SvelteKit’s form actions are excellent for what they do, but developers have been shoehorning mutations into them when a simple function call would be clearer. command handles that case directly.
What this doesn’t replace
Public APIs: Remote functions are for your application’s internal client-server communication. If you need to expose an API for third parties, mobile apps, or other services, you still want +server.ts routes.
GraphQL: If you need a query language with field-level selection, batching across diverse clients, and introspection, remote functions aren’t that. They’re RPC, not query language.
tRPC in polyglot architectures: If your backend serves React, Vue, and Svelte clients, tRPC’s framework-agnostic nature still wins. Remote functions are SvelteKit-specific.
Current limitations
This is experimental software. Be honest about the trade-offs:
API instability: The remote functions API has already had breaking changes (e.g., buttonProps removal in kit 2.50.0). Expect more before stabilization.
Debugging opacity: When a remote function fails, the error originates from a compiler-generated endpoint under /_app/remote. Stack traces are less intuitive than hand-written API routes.
No middleware pattern: tRPC’s middleware chain (auth checks, rate limiting, logging) doesn’t have a direct equivalent. You handle those concerns inside each function or via SvelteKit hooks.
Progressive enhancement requires form: Only the form type works without JavaScript. query and command require JS on the client.
Adapter requirements: Remote functions need server-side rendering support. Fully static sites (adapter-static) can’t use query or command — only prerender.
Which starters benefit most
Looking at our directory, the starters that would gain the most from remote functions are the ones currently maintaining manual API routes or using tRPC for internal communication:
High impact:
- SvelteStack Pro — has dozens of API routes for CRUD operations that could become simple
queryandcommandfunctions - AdminKit Svelte — admin panels are heavy on mutations (create user, update role, delete record).
commandis a natural fit. - SvelteSaaS — subscription management, user settings, and billing operations are all internal mutations
Moderate impact:
- OpenSaaS Svelte — already uses SvelteKit’s form actions well, but some client-side mutations could be cleaner as commands
- SvelteShop — cart operations and product queries are natural candidates
Low impact:
- SvelteBlog Pro — content is static/prerendered.
prerenderremote functions could replace some load functions but the gains are marginal. - SK Minimal — not enough server logic to justify the feature.
- Folio Kit — same. Portfolios are display-only.
Should you use them today?
The honest answer: it depends on your risk tolerance.
Use remote functions if:
- You’re building an internal tool or MVP where API instability is acceptable
- You’re tired of maintaining parallel type definitions for API routes
- You want the simplest possible path from “I need server data” to “I have server data”
- Your project is SvelteKit-only (no external API consumers)
Wait if:
- You’re building for clients who expect production stability
- You need middleware patterns (auth, rate limiting, logging) at the API layer
- You want a community with years of answered Stack Overflow questions
- You’re deploying to a static-only host
The trajectory
Remote functions feel inevitable as SvelteKit’s standard approach to client-server communication. The pattern — compiler-mediated RPC with automatic type inference — is exactly where full-stack frameworks are heading. Next.js has server actions. Solid has server functions. SvelteKit has remote functions.
The experimental flag will drop eventually. When it does, expect starter kits to rapidly adopt the pattern, because it removes real boilerplate without adding abstraction. Until then, it’s an opt-in bet on SvelteKit’s roadmap — and based on the pace of iteration (monthly improvements, active GitHub discussions), it’s a reasonably safe one.
We’ll update our starter reviews to note remote function compatibility as the feature matures.
Get new starters in your inbox
Monthly picks, reviews, and the occasional deep-dive.
You're in! Watch your inbox.
Something went wrong.
No spam. Unsubscribe anytime.
Need pre-built UI components for your SvelteKit project? Check out svelteblocks.com →