eduardweb.
Server ActionsIntermediar#nextjs#react#fullstack#arhitectura

Server Actions vs Route Handlers în Next.js: când alegi fiecare și când te complici

De Alin Pătrașcu, 14 sept. 2026 · 19 vizualizări · 3 like-uri

Postat 14 sept. 2026
typescript
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
import { db } from '@/lib/db';

const schema = z.object({
  bio: z.string().max(160),
});

export async function updateProfile(prevState: any, formData: FormData) {
  const parsed = schema.safeParse({
    bio: formData.get('bio'),
  });

  if (!parsed.success) {
    return { error: 'Bio prea lung (max 160 caractere).' };
  }

  await db.user.update({
    where: { id: 'user_123' },
    data: { bio: parsed.data.bio },
  });

  revalidatePath('/profile');
  return { success: true };
}

Când Next.js a băgat Server Actions în producție, am văzut o grămadă de echipe care au șters instant tot folderul de /api. La un proiect intern cu vreo 14k utilizatori activi am făcut parțial aceeași prostie, doar ca să rescriem bucăți mari două săptămâni mai târziu. Realitatea e simplă: nu e o migrare obligatorie, ci două unelte gândite pentru scenarii complet diferite.

1. Form submit și mutații rapide: Server Actions bate la scor

Dacă ai un formular de setări de profil, un comentariu de adăugat sau o schimbare de status, Server Actions sunt aur curat. Am scăpat de peste 300 de linii de cod boilerplate: adio fetch('/api/user'), adio useState manual pentru stări de loading și erori dacă folosești useActionState.

Marele avantaj e că Server Action-ul rulează direct în contextul serverului tău, are acces la cookies pentru auth și se leagă nativ de cache-ul Next.js prin revalidatePath() sau revalidateTag(). Faci mutația în baza de date, invalidezi ruta și UI-ul se actualizează fără să scrii tu sincronizări manuale pe client.

Trade-off-ul? Cuplarea este extrem de strânsă cu UI-ul aplicației. Nu poți consuma un Server Action dintr-o aplicație mobilă sau dintr-un script extern de automatizare.

2. File upload: depinde enorm de dimensiune

Aici m-am ars cel mai des. Pentru un avatar de 200KB, poți trimite lejer un FormData direct într-un Server Action, îl parsezi cu Zod, îl trântești în S3/Cloudinary și aia a fost.

Problema apare când utilizatorul vrea să încarce fișiere mari, de peste 5-10MB. Dacă trimiți fișierul brut printr-un Server Action, el trece direct prin instanța ta de Node sau lovește limita dură de payload de 4.5MB din serverless-ul de la Vercel/AWS Lambda. Serverul tău înghite memorie aiurea procesând multipart data.

Soluția sănătoasă: folosești un Route Handler clasic (/api/upload) doar ca să generezi un presigned URL de S3/R2, iar clientul face PUT direct către storage provider. Nu lăsa fișiere mari să îți sufoce serverul Next.js.

3. Webhooks și integrări externe: Route Handlers 100%

Aici nu există dezbatere. Dacă integrezi Stripe, Clerk, LemonSqueezy sau un webhook de la GitHub, nu ai cum să folosești Server Actions. De ce? Fiindcă Server Actions sunt gândite strict ca endpoint-uri POST interne pentru Next.js, cu headere specifice, serializare RSC și așteptări de protocol intern.

Un serviciu extern are nevoie de un endpoint REST curat, cu un URL stabil, care să răspundă cu coduri HTTP standard (200, 400, 500) și care să-ți permită să citești direct req.text() pentru validarea semnăturilor criptografice (cum cere Stripe).

Regula de bază pe care o aplicăm acum: Server Actions pentru orice acțiune declanșată direct de om din interfață, Route Handlers pentru mașini, fișiere grele și integrări externe. Voi la ce ați rămas pe /api?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.