15 — Server Functions — Mutations That Run on the Server
The App Router's mechanism for mutations replaces a pattern I had been hand-rolling for years — endpoint, fetch, response handling. The model that clicked: a Server Function is an async function that executes on the server, callable from Client or Server Components, used to handle form submissions and data mutations [1]. In a mutation context they're called Server Actions. They replace the older pattern of writing a separate API endpoint, wiring up a fetch to call it, and handling the response — the function call crosses the network boundary for me.
The mechanism
A Server Function is marked with the 'use server' directive, either at the top of a file (marking every export as a server function) or inside a function body. Once marked, the function runs only on the server — even when invoked from a Client Component, the call is serialized, sent to the server, executed, and the result returned [1].
// app/actions.ts
'use server';
import { revalidateTag } from 'next/cache';
import { db } from '@/lib/db';
export async function createPost(formData: FormData) {
await db.post.create({
data: { title: String(formData.get('title')) },
});
revalidateTag('posts'); // refresh the cached list
}The win is that the Client Component doesn't write a fetch — it just calls the function:
// app/posts/NewPostForm.tsx
'use client';
import { createPost } from '@/app/actions';
export function NewPostForm() {
return (
<form action={createPost}>
<input name="title" />
<button type="submit">Create</button>
</form>
);
}The action prop on a <form> accepts a Server Function directly — progressive enhancement included: the form works even before JavaScript hydrates, because it degrades to a standard POST.
Why this replaces hand-rolled APIs
Before Server Functions, a mutation meant: write an API route handler, write a Client Component that fetches it on submit, handle loading and error states, then revalidate the cache. Server Functions collapse that into one async function — the network call is implicit, and because the function runs on the server, it can directly call the database, the CMS, or any server-only API without exposing those credentials to the browser [1].
The security model matters and is worth stating plainly: Server Functions are server-side code. Anything they import and anything they do stays on the server. The function reference sent to the client is just that — a reference — not the function body. This is why they're the right place for mutations that touch sensitive systems.
Pairing with revalidation
A Server Function typically ends with a revalidation call (revalidateTag or revalidatePath) so the cache reflects the mutation. The pattern: write the data, bust the affected cache tag, the next read serves the fresh result. This composes Server Functions with the caching layer — mutations invalidate the cache, and the rendering layer picks up the new data on the next request.
How I use this
Server Functions are my default for every mutation — form submissions, likes, comments, guestbook entries, anything that writes data. The function lives in app/actions/ (or co-located with the component), runs on the server, touches the database directly, and revalidates the relevant cache tag at the end. The Client Component just calls it and (usually) wires up optimistic updates. I reach for a hand-rolled API route only when I need a non-Next.js client to call the endpoint — webhooks, third-party integrations, public APIs. For internal mutations, Server Functions are simpler and safer.
References
[1] Vercel, "What are Server Functions?," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/getting-started/updating-data
[2] React, "Server Functions," React Docs, 2024. [Online]. Available: https://react.dev/reference/rsc/server-functions
[3] "Next.js Server Actions," YouTube, 2024. [Video]. Available: https://www.youtube.com/watch?v=gQ2bVQPFS4U
[4] Vercel, "How to think about data security in Next.js," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/guides/data-security#data-fetching-approaches
Knowledge check · Question 1 of 5
What is a Server Function?
Comments
Leave a Comment
You must be signed in to comment
0 Comments
No comments yet. Be the first to comment!