AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Blog
  3. 15 — Server Functions — Mutations That Run on the Server

15 — Server Functions — Mutations That Run on the Server

August 13, 20265 min read
Download as Markdown

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.

Hand-rolled — client fetches a separate API route client fetch() API route handler (separate file) database + revalidate explicit network call Server Function — one function, implicit network call client createPost() framework carries the call Server Function (runs on server) database + revalidate no manual fetch/handler the reference crosses the network; the body and its server-only imports stay on the server

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!