TLDR: Next.js Server Actions represent a modern return to the web’s original “form-to-server” roots, effectively collapsing the traditional API layer for internal app mutations. By using the "use server" directive, developers can co-locate database logic directly with UI components, eliminating the need to manually build REST or GraphQL endpoints, define DTOs, or handle client-side cache syncing. While traditional APIs remain necessary for third-party consumers, Server Actions streamline the development lifecycle by treating transport as a framework-managed detail, offering the simplicity of classic multi-page apps with the high-performance interactivity of modern SPAs.
How we got here
Before we had frontend and backend teams, we had documents and servers. The mutation primitive of the server was the HTML <form> element. This form submits to an action url, the server processes it and redirects the user to the result. That’s the flow that was originally specified in the HTML 2.0 specs (https://www.rfc-editor.org/rfc/rfc1866.html#section-8).
This had multiple advantages, for example, an explicit mutation boundary: Clicking submit always meant a server-side state change was about to happen. It also meant that UI and mutation were coupled by default. A big issue of this approach was, however, that each submission usually meant a full-page navigation. Especially for more complex apps, this was not optimal.
The SPA revolution
With Jesse James Garret coining the term AJAX in 2005 (https://designftw.mit.edu/lectures/apis/ajax_adaptive_path.pdf), a new set of techniques was starting to gain traction that allowed developers to make apps more interactive without constant navigation. This brought a new mental model:
- The browser becomes an application runtime.
- The server becomes a data service.
- Navigation becomes a client concern.
This is what we now call SPAs: Single Page Applications or dynamically rewriting the current page instead of loading new pages. The SPA model delivered amazing UX, but it introduced a structural cost. To mutate data, you now typically need:
- a client call (fetch/GraphQL client),
- a server endpoint (REST/GraphQL resolver),
- DTO/schema definitions,
- duplicated validation + auth checks,
- client cache re-sync (invalidate/refetch/reconcile).
In other words, we replaced “form submits to a server handler” with “client orchestration calling a remote interface,” and paid for the flexibility with boilerplate and drift.
The “Thin API” Era
The next wave tried to keep the UX of SPAs while getting back the simplicity of the old coupling. GraphQL originated at Facebook (open-sourced 2015) to address over/under-fetching and to let clients specify their data needs more precisely. It improved reads dramatically, but mutations still required resolvers, schemas, authorization, and client-side cache strategies, so still an explicit API layer.
Frameworks like Remix leaned into the idea that mutations are inherently server-side and made them ergonomic. Remix defines a route action as a server-only function invoked for non-GET requests ( POST/PUT/PATCH/DELETE), integrated with <form> so mutations feel native again.
The unlock for Next.js Server Actions is the React/Next shift toward server-first composition. React’s “Server Components” research (publicly introduced Dec 21, 2020) describes components that can run in a server environment and ship less JS to the client. Server Actions are the convergence point: They aim to restore the original web’s tight coupling between UI and mutation (submit → server executes → UI updates), while keeping SPA-level interactivity and modern component architecture. (https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md)
What server actions are
In Next.js, Server Actions are asynchronous functions that run on the server and are designed specifically for mutations (form submissions, writes, side effects). You’re allowed to reference them from both Server Components and Client Components (e.g., attach them to a <form action={...}>, or call them from the client in supported patterns), while Next.js ensures the code executes server-side. (https://nextjs.org/docs/app/getting-started/updating-data#what-are-server-functions)
They’re enabled by marking a function (or an entire module) with the "use server" directive, which designates it as server-only. A Server Action is the modern equivalent of a form handler, except:
- You don’t define an endpoint
- You don’t manually serialize/deserialize requests
- You can co-locate the mutation right next to the UI that triggers it
- You can invalidate caches, and the page will automatically update
There’s one constraint that shows how it is implemented: inputs and outputs must be serializable (because calls must cross the client-server boundary). At a distance, Server Actions can look like “RPC in React clothing,” but the ergonomics and boundaries are different. With a classic API route (REST / GraphQL / tRPC-like), you explicitly model transport:
- route or procedure name
- request/response objects (or schema)
- client call site (fetch, client SDK)
- auth/CSRF/cookies headers explicitly (or via middleware)
- cache invalidation explicitly (or client cache policies)
With Server Actions, the transport becomes framework-managed:
- You author a function and mark it server-only (
"use server"). - You invoke it from UI primitives (forms), and the framework handles the request plumbing.
This changes how we structure code. Mutation logic becomes UI-adjacent by default. You can keep validation + database writes close to the component that owns the form, without creating a dedicated API surface area just to move bytes around.
Note: You should not call the database directly in the server action, but use the data access layer pattern: https://nextjs.org/blog/security-nextjs-server-components-actions#data-access-layer
Your “public API” and “app mutations” diverge. You still build API routes for true public/third-party consumers, but server actions are optimized for your app’s UI-driven mutations.
One more important detail: Next.js also treats server actions as part of a security model. For example, there’s a configuration around server actions that includes origin/host checks to help prevent CSRF. Again, reinforcing that this is “functions over a managed POST boundary,” not local function calls.
Another great thing about server actions is how easy it is to manage form states with useActionState. Every action call returns the updated form state depending on the action result. (https://react.dev/reference/react/useActionState)
Architectural implications
With server actions as a new tool, we have to rethink our architecture. Let’s take a look at the most important changes:
Disappearing API layer
Now that server actions take care of internal app mutations and server components take care of fetching data, a previously multi-layer stack collapses into a more direct model. What was previously a button that needed event handler setup, a fetch call, an API route, and possibly cache invalidation is now a simple function that is passed to a wrapping form element of the button. This allows mutation logic to be closely co-located with the UI that invokes it.
This does not mean the API layer will disappear completely, since it is still needed for public-facing APIs. But it will reduce the amount of boilerplate needed to be written for internal mutations.
Progressive Enhancement Returns
One thing that often gets overlooked with server actions is that they are deeply integrated into Next’s caching and revalidation system. If a server action mutates state on a page, a simple revalidatePath updates all data on the page, but you can also be more precise with revalidateTag.
Conclusion
The API layer definitely won’t go away, and Next.js server actions aren’t a perfect solution, but they are a refreshing new view on web mutations. Using server actions can improve code readability, but also be used with care. Unspecified return types can lead to data leaking, and being able to mark every function as a publicly accessible endpoint makes it easy to forget auth checks.
It’s time to build with a focus on future-readiness. At &, we specialize in Architecture Consulting to help you weigh the trade-offs of new frameworks against the long-term stability of your core systems. Let’s connect to discuss your current stack or to explore whether it’s the right moment for your team to move away from traditional API layers.
Explore Our Latest Insights
Stay updated with our expert articles and tips.
Discuss Your Web Development Project with Our Experts Today.
Discover how our tailored web development solutions can elevate your business to new heights.
Stay Connected with Us
Follow us on social media for the latest insights and updates in the tech industry.







