Server Actions let you define server-only functions that can be called directly from your components — including from a <form>'s action prop — without manually building a Route Handler for every mutation. This lesson covers defining and using them.
Server-Only Functions Callable from Components
A Server Action is an async function marked with a "use server" directive, either at the top of the function body or at the top of a dedicated file. Next.js compiles it into a secure endpoint automatically — you call it like a normal function from your component, but the code actually runs on the server.
Server Actions are most commonly used for mutations: creating a record, updating a database row, or handling a form submission — replacing the need to build a dedicated Route Handler just to POST some data and then reload or revalidate the page.
// app/actions.ts
"use server";
export async function createPost(formData: FormData) {
const title = formData.get("title") as string;
await db.post.create({ data: { title } });
}
// app/new-post/page.tsx
import { createPost } from "@/app/actions";
export default function NewPostPage() {
return (
<form action={createPost}>
<input name="title" />
<button type="submit">Create Post</button>
</form>
);
}
Submitting this form calls createPost on the server directly — no manual fetch(), no Route Handler, and it still works with JavaScript disabled.
Defining a Server Action
// Inline, inside a Server Component
async function myAction(formData: FormData) {
"use server";
// server-only logic
}
// Or in a dedicated file, applying to every export
"use server";
export async function myAction(formData: FormData) { /* ... */ }
"use server" at the top of a file marks every exported function in it as a Server Action.
"use server" as the first line inside a function marks just that function, usable inline in Server Components.
Server Actions can be called from both Server and Client Components.
When used as a form's action, the first argument is automatically the submitted FormData.
Server Actions Cheat Sheet
Core capabilities and related APIs.
Task
Approach
Define a Server Action
"use server" directive in a function or file
Call from a form
<form action={myAction}>
Call from a button click (Client Component)
onClick={() => myAction(args)}
Refresh data after a mutation
revalidatePath() / revalidateTag()
Track pending state
useFormStatus() (from react-dom)
Calling a Server Action from a Client Component
Server Actions aren't limited to forms — a Client Component can import and call one directly, such as in response to a button click, and Next.js handles the network request behind the scenes automatically.
A Server Action that changes data usually needs to tell Next.js which cached content is now stale, using revalidatePath() or revalidateTag() so the UI reflects the change immediately after the action completes.
"use server";
import { revalidatePath } from "next/cache";
export async function createPost(formData: FormData) {
await db.post.create({ data: { title: formData.get("title") as string } });
revalidatePath("/posts");
}
Common Mistakes
Forgetting revalidatePath()/revalidateTag() after a mutation, leaving the UI showing stale data.
Treating Server Actions as fully public, unauthenticated endpoints — they still need their own authorization checks.
Trying to return non-serializable values (like a class instance) directly from a Server Action to a Client Component.
Not validating FormData input, trusting it the same way you would trust a fully-typed function call.
Key Takeaways
Server Actions are server-only functions, callable directly from components, marked with "use server".
They can be used as a form's action or called directly from event handlers in Client Components.
They commonly replace hand-built Route Handlers for simple mutations.
Always revalidate affected paths/tags after a mutation so the UI reflects the change.
Server Actions still need explicit authorization checks — they are not automatically protected.
Pro Tip
Treat every Server Action as if it were a public API endpoint when it comes to security — validate its inputs and check the caller's permissions inside the action itself, since anyone who can inspect your app's network requests can technically call a Server Action directly with arbitrary arguments.
You now understand Server Actions. Next, see them in practice by building complete forms with validation and pending states.