Frontend 7 jul 2026 · 7 min de lectura

Server Actions en Next.js: dónde brillan y dónde me niego a usarlas

Yohangel Ramos

Yohangel Ramos

Tech Lead · Senior Fullstack Developer

Las Server Actions de Next.js son la mejor y la peor idea del framework, según dónde las pongas. Para mutaciones de formulario — crear, editar, borrar desde la UI — eliminan una capa entera de boilerplate: no defines endpoint, no serializas a mano, no gestionas fetch ni estados de carga con useEffect. Pero he visto (y he tenido que deshacer) proyectos donde se convirtieron en la única forma de hablar con el servidor, y ahí el patrón se rompe: lógica de negocio atrapada en el framework, imposible de consumir desde otro cliente, y un grafo de invalidaciones que nadie entiende. Mi criterio después de usarlas en producción: las Server Actions son la capa de interacción de la UI, no la API de tu producto. Este artículo es la línea que trazo y por qué.

Donde brillan: la mutación de formulario de toda la vida

El caso feliz es un formulario que muta datos y revalida la vista. Con action, validación con Zod compartido y estado pendiente del propio React:

// app/proyectos/actions.ts
'use server';

import { revalidatePath } from 'next/cache';
import { proyectoSchema } from '@/schemas/proyecto';

export async function crearProyecto(formData: FormData) {
  const session = await getSession();
  if (!session) throw new Error('No autorizado');

  const parsed = proyectoSchema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) {
    return { error: parsed.error.flatten().fieldErrors };
  }

  await prisma.proyecto.create({
    data: { ...parsed.data, ownerId: session.userId },
  });

  revalidatePath('/proyectos');
  return { ok: true };
}

Cero endpoints, cero cliente HTTP, el tipo de retorno viaja inferido hasta el componente. Para el 80% de las mutaciones de un panel interno, esto es todo lo que necesitas, y volver a escribir route handlers para esos casos es nostalgia, no ingeniería.

La línea roja: lógica de negocio que vive en la action

El problema empieza cuando la action deja de ser un adaptador y se convierte en el hogar de la lógica. Una action que calcula precios, orquesta tres servicios y decide reglas de negocio es código que solo puede invocarse desde un componente React de ese proyecto Next.js. El día que llega la app móvil, el cron job o el equipo que quiere un endpoint público, esa lógica hay que exhumarla.

Mi regla estructural: la action llama a un servicio, y el servicio no sabe que Next.js existe.

// services/proyectos.ts — framework-agnostic, testeable en aislamiento
export async function crearProyectoParaUsuario(
  input: ProyectoInput,
  userId: string
) {
  // toda la lógica de negocio vive aquí
}

La action queda en tres líneas: autenticar, parsear, delegar. Si mañana necesito exponer lo mismo por route handler o por un worker de SQS, el servicio ya está listo. Elegí esta separación aun sabiendo que duplica un poco de ceremonia; a cambio, ninguna decisión de negocio queda rehén del framework.

💡 Una Server Action es un mecanismo de transporte con azúcar sintáctico, no una capa de arquitectura. Si borras Next.js de tu proyecto y con él se va lógica de negocio, tenías la lógica en el sitio equivocado.

Los límites operativos que nadie te cuenta hasta producción

Son POST secuenciales. Las Server Actions se ejecutan en serie por defecto desde el mismo cliente: si el usuario dispara tres, se encolan. Para un formulario da igual; para interacciones de alta frecuencia (autoguardado, drag and drop de un tablero) es un cuello de botella que descubres tarde.

No son cancelables ni cacheables. Un GET a un route handler puede cachearse en CDN y abortarse con AbortController. Una action, no. Todo lo que sea lectura — búsqueda, autocompletar, filtros — no tiene nada que hacer en una action: eso es un route handler o directamente un Server Component que lee de la base de datos.

El error handling es opaco. Un throw en una action llega al cliente como un error genérico en producción (por diseño, para no filtrar internals). Eso obliga a modelar los errores esperables como valores de retorno — el { error } del ejemplo — y reservar el throw para lo verdaderamente excepcional. Es más Result que Exception, y conviene decidirlo desde el día uno para no mezclar estilos.

El criterio en una frase

Mutación iniciada por un usuario desde la UI de ese mismo proyecto: Server Action que delega en un servicio. Lecturas, APIs consumidas por terceros, webhooks, alta frecuencia, cualquier cosa que un día pueda necesitar otro cliente: route handler o backend propio. Con esa línea trazada, las Server Actions son una herramienta excelente — pequeña, aburrida y en su sitio, que es exactamente como me gustan las herramientas.

Yohangel Ramos

Escrito por Yohangel Ramos

Senior Fullstack Developer y Tech Lead. Construyo con React, Next.js, Nest.js y AWS — y escribo sobre lo que aprendo en el camino.

Hablemos →

Sigue leyendo

IA

Embeddings más baratos: recortar dimensiones y cuantizar sin perder recall

IA

Qué va a pasar con el desarrollo de software: predicciones con fechas (julio 2026)