eduardweb.
Server ActionsIntermediar#server-actions#nextjs#backend#web-dev#api-routes

Server Actions vs API Routes în Next.js: Din tranșee, după un proiect cu 12k useri

De Răzvan Matei, 22 mai 2026 · 6 vizualizări · 2 like-uri

Postat 22 mai 2026
typescript
// app/actions/subscribe.ts
'use server';

import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
});

export async function subscribeNewsletter(prevState: any, formData: FormData) {
  const validatedFields = schema.safeParse({
    email: formData.get('email'),
  });

  if (!validatedFields.success) {
    return { error: 'Email invalid!' };
  }

  try {
    // db.subscribe(validatedFields.data.email);
    return { success: true };
  } catch (err) {
    return { error: 'Eroare la salvare în baza de date.' };
  }
}

S-a făcut enorm de mult hype în jurul Server Actions de când au devenit stabile în Next.js. Recunosc, am picat și eu în capcană. La un proiect recent, cu vreo 12.000 de utilizatori activi, am zis să fiu "modern" și să scriu totul cu Server Actions. Mi-am luat câteva palme tehnice destul de dureroase.

După luni de refactoring și optimizări, m-am lămurit cum stă treaba. Server Actions nu înlocuiesc complet API routes. Sunt instrumente diferite pentru probleme diferite.

1. Formularul simplu: Unde Server Actions sunt geniale

Dacă ai de făcut un formular de contact, un update de profil sau un newsletter sign-up, Server Actions sunt absolut geniale. Economisești cam 30% din codul pe care l-ai fi scris înainte pentru că scapi de:

  • Definit endpoint-uri de API separate (/api/subscribe).
  • Gestionat stări de fetch, loading și error prin useState (acum ai useActionState și useTransition).
  • Scris tipuri TS duplicate pentru request și response.

Totul se întâmplă în același fișier sau într-un modul dedicat de acțiuni. Primești datele direct ca FormData, le validezi cu Zod și le trântești în baza de date.

Trade-off-ul sincer: Logica asta e strâns legată de Next.js. Dacă peste 6 luni clientul vrea o aplicație mobilă nativă care să facă exact același lucru, nu poți apela acea acțiune direct. Va trebui să refactorizezi logica într-un serviciu comun și să expui un API route.

2. File Upload: Zona gri unde poți bloca serverul

Am încercat să facem upload de imagini de produs direct printr-un Server Action. Pe foaie, arată simplu: iei File din FormData, îl transformi în buffer și-l trimiți în S3.

În realitate, la fișiere mai mari de 4-5 MB, am observat că serverul de Node.js începea să gâfâie. Server Actions serializează payload-ul într-un mod destul de opac pentru a menține starea paginii, iar asta mănâncă memorie RAM și CPU aiurea pe server. În plus, nu ai un control nativ bun pe progress bar (cât la sută s-a încărcat).

Cum facem acum: Pentru fișiere, folosim tot API Routes clasice cu suport de streaming sau, cel mai curat, generăm un presigned URL printr-un Server Action, iar upload-ul propriu-zis îl facem direct din browser în S3.

3. Webhook-uri și integrări externe: Exclusiv API Routes

Aici nu există dubii. Dacă Stripe îți trimite un webhook când s-a efectuat o plată, sau dacă ai nevoie de un endpoint pe care să-l apeleze un cron job extern, Server Actions sunt complet inutile.

Server Actions au nevoie de headere specifice Next.js, de un token de securitate (anti-CSRF) generat de framework și sunt gândite strict pentru interacțiunea client-server din interiorul aplicației tale. Pentru orice apel din exterior, ai nevoie de un API Route clasic (app/api/webhook/route.ts), unde poți valida semnătura Stripe și returna un Response.json({ received: true }) curat.

Concluzia mea

Regula mea simplă de acum este:

  • Server Actions: Când acțiunea pornește de la un utilizator real din browserul tău și modifică starea UI-ului (mutări de pagini, submit-uri, mutări în coș).
  • API Routes: Când ai nevoie de un endpoint public, webhook-uri, upload masiv de fișiere sau vrei să separi complet backend-ul de frontend pentru viitoare integrări.

Voi ce abordare folosiți pentru formularele complexe? Ați renunțat complet la folderul /api?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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