Technical
Next.js Server Actions: The Feature That Earned My Trust
When Next.js server actions launched I rolled my eyes. Another abstraction, another bit of magic, another debugging challenge waiting to happen. I used API routes for forms because they were explicit. Five months later I reach for server actions first and API routes only when I need them.
The Shape of the Win
A server action is a function that runs on the server but you call it from client JSX like it's local. The network, the serialization, the error handling all happen inside the framework.
'use server';
export async function subscribe(formData: FormData) {
const email = formData.get('email') as string;
await addSubscriber(email);
}
// in a client component
<form action={subscribe}>
<input name="email" />
<button>Subscribe</button>
</form>That's the whole form. No API route, no fetch call, no state machine.
What Made Me Trust It
Three things converted me:
- Progressive enhancement: forms work without JS
- Type safety: the function signature crosses the boundary
- Revalidation:
revalidatePathafter a write is one line
Progressive enhancement was the killer. Clients care that forms work on bad networks and flaky mobile. Server actions give that to me for free.
When I Still Use API Routes
Anything that isn't a form submission. Webhooks from third-party services, cron endpoints, public REST contracts. Server actions are for the internal form-to-mutation path. API routes are for everything else.
See the Next.js server actions docs.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read