---
title: Server Actions
nav_title: Server Actions
description: Learn how to mutate data with Server Actions.
related:
  title: Next Steps
  description: For more information on what to do next, we recommend the following sections
  links:
    - app/api-reference/functions/cookies
---

[Server Actions](#server-actions) are an **alpha** feature in Next.js, built on top of React [Actions](#actions). They enable server-side data mutations, reduced client-side JavaScript, and progressively enhanced forms. They can be defined inside Server Components and/or called from Client Components:

**With Server Components:**

```jsx filename="app/add-to-cart.js" highlight={5, 6, 13}
import { cookies } from 'next/headers'

// Server action defined inside a Server Component
export default function AddToCart({ productId }) {
  async function addItem(data) {
    'use server'

    const cartId = cookies().get('cartId')?.value
    await saveToDb({ cartId, data })
  }

  return (
    <form action={addItem}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}
```

**With Client Components:**

```jsx filename="app/actions.js" highlight={1, 3}
'use server'

export async function addItem(data) {
  const cartId = cookies().get('cartId')?.value
  await saveToDb({ cartId, data })
}
```

```jsx filename="app/add-to-cart.js" highlight={1, 3, 8}
'use client'

import { addItem } from './actions.js'

// Server Action being called inside a Client Component
export default function AddToCart({ productId }) {
  return (
    <form action={addItem}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}
```

Rather than needing to manually create an API endpoint, Server Actions automatically create an endpoint for Next.js to use behind the scenes. When calling a Server Action, Next.js sends a `POST` request to the page you're on with metadata for which action to run.

Server Actions inherit the same runtime (either [Node.js or Edge](/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes)) defined by the `page` or `layout` they're used on. Currently, if a route uses a Server Action, it is required to [render dynamically](/docs/app/building-your-application/rendering/static-and-dynamic).

> **Good to know:**
>
> - Using Server Actions will opt into running the React `experimental` channel.
> - React Actions, `useOptimistic`, and `useFormStatus` are not Next.js or React Server Components specific features.
> - Next.js integrates React Actions into the Next.js App Router, bundler, and caching system, including adding data mutation APIs like `revalidateTag` and `revalidatePath`.

## Convention

You can enable Server Actions in your Next.js project by enabling the **experimental** `serverActions` flag.

```js filename="next.config.js"
module.exports = {
  experimental: {
    serverActions: true,
  },
}
```

### Creation

Server Actions can be defined in two places:

- Inside the component that uses it (Server Components only)
- In a separate file (Client and Server Components), for reusability. You can define multiple Server Actions in a single file.

#### With Server Components

Create a Server Action by defining an asynchronous function with the `"use server"` directive at the top of the function body. This function should have **serializable arguments** and a **serializable return value** based on the React Server Components protocol.

```jsx filename="app/server-component.js" highlight={2}
export default function ServerComponent() {
  async function myAction() {
    'use server'
    // ...
  }
}
```

#### With Client Components

If you're using a Server Action inside a Client Component, create your action in a separate file with the "use server" directive at the top of the file. Then, import the Server Action into your Client Component:

```js filename="app/actions.js" highlight={1}
'use server'

export async function myAction() {
  // ...
}
```

```jsx filename="app/client-component.js" highlight={1}
'use client'

import { myAction } from './actions'

export default function ClientComponent() {
  return (
    <form action={myAction}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}
```

> **Good to know**: When using a top-level `"use server"` directive, all exports below will be considered Server Actions. You can have multiple Server Actions in a single file.

### Invocation

You can invoke Server Actions using the following methods:

- Using `action`: React's `action` prop allows invoking a Server Action on a `<form>` element.
- Using `formAction`: React's `formAction` prop allows handling `<button>`, `<input type="submit">`, and `<input type="image">` elements in a `<form>`.
- Custom Invocation with `startTransition`: Invoke Server Actions without using `action` or `formAction` by using `startTransition`. This method **disables [Progressive Enhancement](#progressive-enhancement)**.

#### `action`

You can use React's `action` prop to invoke a Server Action on a `form` element. Server Actions passed with the action prop act as asynchronous side effects in response to user interaction.

```jsx filename="app/add-to-cart.js"
import { cookies } from 'next/headers'

export default function AddToCart({ productId }) {
  async function addItem(data) {
    'use server'

    const cartId = cookies().get('cartId')?.value
    await saveToDb({ cartId, data })
  }

  return (
    <form action={addItem}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}
```

> **Good to know**: An `action` is similar to the HTML primitive [`action`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action)

#### `formAction`

You can use `formAction` prop to handle **Form Actions** on elements such as `button`, `input type="submit"`, and `input type="image"`. The `formAction` prop takes precedence over the form's `action`.

```jsx filename="app/form.js" highlight={15}
export default function Form() {
  async function handleSubmit() {
    'use server'
    // ...
  }

  async function submitImage() {
    'use server'
    // ...
  }

  return (
    <form action={handleSubmit}>
      <input type="text" name="name" />
      <input type="image" formAction={submitImage} />
      <button type="submit">Submit</button>
    </form>
  )
}
```

> **Good to know**: A `formAction` is the HTML primitive [`formaction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#formaction). React now allows you to pass functions to this attribute.

#### Custom invocation using `startTransition`

You can also invoke Server Actions without using `action` or `formAction`. You can achieve this by using `startTransition` provided by the `useTransition` hook, which can be useful if you want to use Server Actions outside of forms, buttons, or inputs.

> **Good to know**: Using `startTransition` disables the out-of-the-box Progressive Enhancement.

```jsx filename="app/components/example-client-component.js" highlight={3, 7, 10}
'use client'

import { useTransition } from 'react'
import { addItem } from '../actions'

function ExampleClientComponent({ id }) {
  let [isPending, startTransition] = useTransition()

  return (
    <button onClick={() => startTransition(() => addItem(id))}>
      Add To Cart
    </button>
  )
}
```

```js filename="app/actions.js"
'use server'

export async function addItem(id) {
  await addItemToDb(id)
  // Marks all product pages for revalidating
  revalidatePath('/product/[id]')
}
```

#### Custom invocation without `startTransition`

If you aren't doing [Server Mutations](#server-mutations), you can directly pass the function as a prop like any other function.

```tsx filename="app/posts/[id]/page.tsx" switcher
import kv from '@vercel/kv'
import LikeButton from './like-button'

export default function Page({ params }: { params: { id: string } }) {
  async function increment() {
    'use server'
    await kv.incr(`post:id:${params.id}`)
  }

  return <LikeButton increment={increment} />
}
```

```jsx filename="app/posts/[id]/page.js" switcher
import kv from '@vercel/kv'
import LikeButton from './like-button'

export default function Page({ params }) {
  async function increment() {
    'use server'
    await kv.incr(`post:id:${params.id}`)
  }

  return <LikeButton increment={increment} />
}
```

```tsx filename="app/post/[id]/like-button.tsx" switcher
'use client'

export default function LikeButton({
  increment,
}: {
  increment: () => Promise<void>
}) {
  return (
    <button
      onClick={async () => {
        await increment()
      }}
    >
      Like
    </button>
  )
}
```

```jsx filename="app/post/[id]/like-button.js" switcher
'use client'

export default function LikeButton({ increment }) {
  return (
    <button
      onClick={async () => {
        await increment()
      }}
    >
      Like
    </button>
  )
}
```

### Enhancements

#### Experimental `useOptimistic`

The experimental `useOptimistic` hook provides a way to implement optimistic updates in your application. Optimistic updates are a technique that enhances user experience by making the app appear more responsive.

When a Server Action is invoked, the UI is updated immediately to reflect the expected outcome, instead of waiting for the Server Action's response.

```jsx filename="app/thread.js"
'use client'

import { experimental_useOptimistic as useOptimistic, useRef } from 'react'
import { send } from './actions.js'

export function Thread({ messages }) {
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [...state, { message: newMessage, sending: true }]
  )
  const formRef = useRef()

  return (
    <div>
      {optimisticMessages.map((m) => (
        <div>
          {m.message}
          {m.sending ? 'Sending...' : ''}
        </div>
      ))}
      <form
        action={async (formData) => {
          const message = formData.get('message')
          formRef.current.reset()
          addOptimisticMessage(message)
          await send(message)
        }}
        ref={formRef}
      >
        <input type="text" name="message" />
      </form>
    </div>
  )
}
```

#### Experimental `useFormStatus`

The **experimental** `useFormStatus` hook can be used within Form Actions, and provides the `pending` property.

```jsx filename="app/form.js"
'use client'

import { experimental_useFormStatus as useFormStatus } from 'react-dom'

function Submit() {
  const { pending } = useFormStatus()

  return (
    <input
      type="submit"
      className={pending ? 'button-pending' : 'button-normal'}
      disabled={pending}
    >
      Submit
    </input>
  )
}
```

#### Progressive Enhancement

Progressive Enhancement allows a `<form>` to function properly without JavaScript, or with JavaScript disabled. This allows users to interact with the form and submit data even if the JavaScript for the form hasn't been loaded yet or if it fails to load.

Both Server Form Actions and Client Form Actions support Progressive Enhancement, using one of two strategies:

- If a **Server Action** is passed directly to a `<form>`, the form is interactive **even if JavaScript is disabled**.
- If a **Client Action** is passed to a `<form>`, the form is still interactive, but the action will be placed in a queue until the form has hydrated. The `<form>` is prioritized with Selective Hydration, so it happens quickly.

```jsx filename="app/components/example-client-component.js"
'use client'

import { useState } from 'react'
import { handleSubmit } from './actions.js'

export default function ExampleClientComponent({ myAction }) {
  const [input, setInput] = useState()

  return (
    <form action={handleSubmit} onChange={(e) => setInput(e.target.value)}>
      {/* ... */}
    </form>
  )
}
```

In both cases, the form is interactive before hydration occurs. Although Server Actions have the additional benefit of not relying on client JavaScript, you can still compose additional behavior with Client Actions where desired without sacrificing interactivity.

### Size Limitation

By default, the maximum size of the request body sent to a Server Action is 1MB. This prevents large amounts of data being sent to the server, which consumes a lot of server resource to parse.

However, you can configure this limit using the **experimental** `serverActionsBodySizeLimit` option. It can take the number of bytes or any string format supported by bytes, for example `1000`, `'500kb'` or `'3mb'`.

```js filename="next.config.js"
module.exports = {
  experimental: {
    serverActions: true,
    serverActionsBodySizeLimit: '2mb',
  },
}
```

## Examples

### Usage with Client Components

#### Import

Server Actions **cannot** be _defined_ within Client Components, but they can be _imported_. To use Server Actions in Client Components, you can import the action from a file containing a top-level `"use server"` directive.

```js filename="app/actions.js" highlight={1}
'use server'

export async function addItem() {
  // ...
}
```

```jsx filename="app/components/example-client-component.js" highlight={3, 7, 10}
'use client'

import { useTransition } from 'react'
import { addItem } from '../actions'

function ExampleClientComponent({ id }) {
  let [isPending, startTransition] = useTransition()

  return (
    <button onClick={() => startTransition(() => addItem(id))}>
      Add To Cart
    </button>
  )
}
```

#### Props

Although [importing](#import) Server Actions is recommended, in some cases you might want to pass down a Server Action to a Client Component as a prop.

For example, you might want to use a dynamically generated value within the action. In that case, passing a Server Action down as a prop might be a viable solution.

```jsx filename="app/components/example-server-component.js"
import { ExampleClientComponent } from './components/example-client-component.js'

function ExampleServerComponent({ id }) {
  async function updateItem(data) {
    'use server'
    modifyItem({ id, data })
  }

  return <ExampleClientComponent updateItem={updateItem} />
}
```

```jsx filename="app/components/example-client-component.js"
'use client'

function ExampleClientComponent({ updateItem }) {
  return (
    <form action={updateItem}>
      <input type="text" name="name" />
      <button type="submit">Update Item</button>
    </form>
  )
}
```

### On-demand Revalidation

Server Actions can be used to revalidate data on-demand by path ([`revalidatePath`](/docs/app/api-reference/functions/revalidatePath)) or by cache tag ([`revalidateTag`](/docs/app/api-reference/functions/revalidateTag)).

```js
import { revalidateTag } from 'next/cache'

async function revalidate() {
  'use server'
  revalidateTag('blog-posts')
}
```

Learn more about [caching and revalidating](/docs/app/building-your-application/caching).

### Validation

The data passed to a Server Action can be validated or sanitized before invoking the action. For example, you can create a wrapper function that receives the action as its argument, and returns a function that invokes the action if it's valid.

```js filename="app/actions.js"
'use server'

import { withValidate } from 'lib/form-validation'

export const action = withValidate((data) => {
  // ...
})
```

```js filename="lib/form-validation.js"
export function withValidate(action) {
  return async (formData) => {
    'use server'

    const isValidData = verifyData(formData)

    if (!isValidData) {
      throw new Error('Invalid input.')
    }

    const data = process(formData)
    return action(data)
  }
}
```

### Using headers

You can read incoming request headers such as `cookies` and `headers` within a Server Action.

```js highlight={6}
import { cookies } from 'next/headers'

async function addItem(data) {
  'use server'

  const cartId = cookies().get('cartId')?.value

  await saveToDb({ cartId, data })
}
```

Additionally, you can modify cookies within a Server Action.

```js highlight={7, 9, 10, 11, 12, 13, 14}
import { cookies } from 'next/headers';

async function create(data) {
  'use server';

  const cart = await createCart():
  cookies().set('cartId', cart.id)
  // or
  cookies().set({
    name: 'cartId',
    value: cart.id,
    httpOnly: true,
    path: '/'
  })
}
```

### Redirection

You can also trigger a redirection within a Server Action by using the `redirect` function.

```js highlight={8}
import { redirect } from 'next/navigation'

async function addItem(data) {
  'use server'

  await saveToDb({ data })

  redirect('/success')
}
```

## Glossary

### Actions

Actions are an experimental feature in React, allowing you to run `async` code in response to a user interaction.

Actions are not Next.js or React Server Components specific, however, they are not yet available in the stable version of React. When using Actions through Next.js, you are opting into using the React `experimental` channel.

Actions are defined through the `action` prop on an element. Typically when building HTML forms, you pass a URL to the [`action` prop](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action). With Actions, React now allows you to pass a function directly.

React also provides built-in solutions for [optimistic updates](#experimental-useoptimistic) with Actions. It's important to note new patterns are still being developed and new APIs may still be added.

### Form Actions

[Actions](#actions) integrated into the web standard `<form>` API, and enable out-of-the-box progressive enhancement and [loading states](#experimental-useformstatus). Similar to the HTML primitive [`formaction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#formaction).

### Server Functions

Functions that run on the server, but can be called on the client.

### Server Actions

[Server Functions](#server-functions) called as an action.

Server Actions can be progressively enhanced by passing them to a [`form` element's `action` prop](#invocation). The form is interactive before any client-side JavaScript has loaded. This means React hydration is not required for the form to submit.

### Server Mutations

[Server Actions](#server-actions) that mutates your data and calls `redirect`, `revalidatePath`, or `revalidateTag`.
