Server Actions
Run server-side code directly from a form or button using the "use server" directive — no API endpoint required.
What Is a Server Action?
A Server Action is an async function marked with "use server" that always runs on the server, even when it's called from a Client Component in the browser. It gives you a way to mutate data — creating a record, updating a row — without hand-building a Route Handler and a fetch call to reach it.
Defining a Server Action
You can mark a whole file as server-only actions, or mark an individual function inline inside a Server Component.
// app/actions.ts'use server';
export async function createPost(formData) { const title = formData.get('title'); await db.post.create({ data: { title } }); revalidatePath('/blog');}Using It in a Form
Pass a Server Action directly to a form's action prop. Next.js handles the submission — including progressive enhancement, so the form still works even before client JavaScript finishes loading.
// app/blog/new/page.tsx — Server Componentimport { createPost } from '../../actions';
export default function NewPostPage() { return ( <form action={createPost}> <input name="title" placeholder="Post title" /> <button type="submit">Create Post</button> </form> );}Because the form posts using standard HTML form semantics under the hood, it keeps working even if JavaScript hasn't loaded yet — a meaningful reliability win over a purely client-side fetch-based submit handler.
Calling a Server Action from an Event Handler
Server Actions also work from a Client Component's regular event handlers, not just a form's action prop — useful for a "like" button or any single-click mutation.
'use client';import { likePost } from '../actions';
export default function LikeButton({ postId }) { return ( <button onClick={() => likePost(postId)}> 👍 Like </button> );}How It Works Under the Hood
Next.js compiles a Server Action into a reference the client can safely call — under the hood, calling it triggers a POST request back to the server, where the actual function body runs. The client never sees your database queries or server-only logic; it only ever gets a callable reference.
Common Beginner Mistakes
Without revalidatePath or revalidateTag, the UI won't reflect the change until the cache naturally expires or the user hard-refreshes.
Every call is a network round-trip to the server — don't call one in a tight loop or expect synchronous, instantaneous execution.
FAQs
No — they overlap for internal mutations, but Route Handlers are still needed for public APIs, webhooks, and custom response formats.
Yes — it can return a value the caller awaits, which is commonly combined with the useFormStatus and useFormState (useActionState) hooks for pending/error UI.
Summary
Server Actions let you write server-side mutations as plain async functions, callable directly from forms and event handlers. Next, you'll build a complete form with validation and pending states around this pattern.