Skip to content

What Are Server Actions?

A Server Action is an async function marked with the "use server" directive that runs only on the server, and you can call it straight from a <form> or from a Client Component without writing an API route.

There are two ways to mark a function as a Server Action. You can add "use server" at the top of an inline async function inside a Server Component, or you can add 'use server' at the top of a whole module file so every export in that file becomes an action.

// app/page.tsx — an inline Server Action inside a Server Component
export default function Page() {
async function createTodo(formData: FormData) {
'use server'
const title = String(formData.get('title'))
await db.todo.create({ data: { title } })
}
return (
<form action={createTodo}>
<input name="title" />
<button type="submit">Add</button>
</form>
)
}

When several components need the same action, put it in a dedicated file. Add 'use server' once at the top and every export becomes a callable action. This keeps mutation logic in one place and lets Client Components import it.

// app/actions.ts — every export here is a Server Action
'use server'
export async function createTodo(formData: FormData) {
const title = String(formData.get('title'))
await db.todo.create({ data: { title } })
}
export async function deleteTodo(id: string) {
await db.todo.delete({ where: { id } })
}

Calling from a form and from a Client Component

Section titled “Calling from a form and from a Client Component”

A Server Action can be wired directly to a form with <form action={createTodo}>, and Next.js posts the form data to the action on the server. It can also be imported into a Client Component and called like a normal function — Next.js turns that call into a network request for you.

// app/todo-button.tsx — calling an action from a Client Component
'use client'
import { deleteTodo } from './actions'
export function DeleteButton({ id }: { id: string }) {
return <button onClick={() => deleteTodo(id)}>Delete</button>
}

A Route Handler in route.ts is a public URL you design, wire up, and fetch by hand. A Server Action is a function you call directly; Next.js generates the endpoint and the network call for you and supports progressive enhancement through forms. Reach for a Route Handler when you need a real public API or webhook; reach for a Server Action for form and mutation flows inside your own app.

graph LR
  A["form or Client Component"] -->|"calls action"| B["Next.js generated endpoint"]
  B -->|"runs on server only"| C["Server Action function"]
  C -->|"reads or writes"| D["Database"]
How a Server Action call reaches the server
What does the "use server" directive mark a function as?
What happens when you add 'use server' at the top of a module file?
How do you call a Server Action from a Client Component?
When should you reach for a Route Handler instead of a Server Action?