Server Actions in Next.js: A Practical Introduction

What Server Actions are, how to define and call one from a form or event handler, and what happens on the server during a single roundtrip.

7 min read

Next.js Server Actions are async functions that run on the server and handle mutations. You attach one to a form or an event handler, and Next.js calls it over a POST request. The function updates data on the server, then the UI refreshes in a single roundtrip.

A Server Action is a Server Function used for mutations. The broader Server Function term covers any async function the server exposes, while Server Actions are the form and mutation side you reach for most often.

index.tsindex.ts
// app/actions.ts
'use server'
 
export async function createPost(formData: FormData) {
  const title = formData.get('title')?.toString()
  return { title }
}

The use server directive at the top of this file marks every exported function as server-only code. The browser can call these functions, but their code never ships in the client bundle.

Now call it from a form. This page is a Server Component, and the form passes the function straight to the action attribute.

App.tsxApp.tsx
// app/page.tsx
import { createPost } from './actions'
 
export default function Page() {
  return (
    <form action={createPost}>
      <label>Title <input name="title" required /></label>
      <button type="submit">Create post</button>
    </form>
  )
}

When someone submits the form, the browser sends the fields as FormData and calls createPost on the server. The form also works before JavaScript loads, because React submits it with progressive enhancement.

Two ways to mark server code

The use server directive has two placements. At the top of a file it marks every exported function. Inside a function body it marks only that one function.

PlacementEffect
Top of a fileEvery export in the file runs on the server
Inside a function bodyOnly that function runs on the server

The file form is the common one, because it keeps related actions together in one module. The inline form is useful when one page needs an action that closes over its props. See the use server directive for the full placement rules.

Ways to invoke a Server Action

The form action above is the primary path, but two more exist. A button can use formAction, and a Client Component can call the function from an event handler.

App.tsxApp.tsx
// app/like-button.tsx
'use client'
 
import { incrementLike } from './actions'
 
export function LikeButton({ likes }: { likes: number }) {
  return (
    <button onClick={() => incrementLike()}>Like ({likes})</button>
  )
}

This component needs use client because event handlers run in the browser. incrementLike is another export from app/actions.ts, so it stays a server function, and the click sends it over a POST just like the form does.

The count on screen does not change on its own. The click reaches the server, but the button keeps rendering the likes prop it was given until the page revalidates or you hold the value in client state.

What happens in a roundtrip

When a Server Action runs, Next.js sends a POST to the server with the serialized arguments. The server runs the function and can respond with updated UI and new data together, so a mutation and its result arrive in one response. Actions use the POST method, and it is the only method that can invoke one.

The returned value is serialized and sent back, which is why createPost can return the title object. On the server, the function can reach databases, cookies, and other server-only APIs that never touch the browser.

Two limits are worth knowing early. The client dispatches actions one at a time, so triggering three in a row queues them rather than running them in parallel. Action request bodies are also capped at 1MB by default, which you raise through the serverActions option in the Next.js config when a form carries larger uploads.

Server Actions run on the server, not the client

The function body always executes on the server, even when a Client Component calls it. That separation is what lets an action read secrets or write to a database without exposing those details to visitors.

The trade-off is that every action is reachable over HTTP, not just through your UI. Anyone who can construct a POST can attempt to call it, so an action must verify the caller itself rather than trusting the button that triggered it.

Next.js does add framework-level protection. It compares the request Origin against the Host and rejects mismatches, and it encrypts action references at build time so unused actions leave no public endpoint behind.

Those checks stop a cross-site request. They say nothing about whether this particular user may change this particular record, which is the part your code has to answer.

When to use a Server Action

Use a Server Action for mutations: create, update, delete, or any state change.

Do not use one to fetch read-only data. A Server Component already fetches directly on the server without a roundtrip, and because actions dispatch one at a time, a list of reads runs in sequence instead of in parallel. Fetch in the component, mutate in the action.

If an outside system needs to call your code, an action is also the wrong shape, since it has no stable URL to hand out. That job belongs to a Route Handler.

See how to mutate data with a Server Action for the working pattern, and securing Server Actions for the auth checks to add before shipping.

Rune AI

Rune AI

Key Insights

  • A Server Action is an async function that runs on the server and handles mutations.
  • Mark server code with the use server directive at the top of a file or inside a function.
  • Invoke an action through a form action, a button formAction, or a client event handler.
  • Actions use POST only, and the server can return updated UI and data in one roundtrip.
  • Verify authentication inside every action before mutating data.
RunePowered by Rune AI

Frequently Asked Questions

Are Server Actions and Server Functions the same thing?

A Server Action is a Server Function used for mutations, such as form submissions. Server Function is the broader term for any async function the server exposes.

Do Server Actions work without JavaScript?

Yes. Forms that call Server Actions in Server Components submit through progressive enhancement, so they work before JavaScript loads or when it is disabled.

Can a Server Action run on the client?

No. The function always runs on the server. Client Components can call a Server Action, but the code itself is never sent to the browser.

Conclusion

Server Actions give you a server-only function you can call from a form or event handler over a POST request. Mark code with use server, attach it to a form action, and the mutation runs on the server in a single roundtrip.