
Je suis Mathieu Ponton, Co-Founder & ingénieur logiciel chez Apogée Consult à Lyon. Ingénieur diplômé de Polytech Lyon (Informatique), j'ai fait trois ans en apprentissage, partagés entre la Métropole de Lyon (inclusion numérique avec Res'in et sobriété énergétique avec Écolyo) et Superwyze, une startup medtech (POCs, dont certains aujourd'hui industrialisés, et travail sur des codebases existantes). J'ai livré plus de 10 projets en production (web, mobile et IA / RAG) pour des PME, startups et organisations publiques.
Server Actions : les 3 contextes où on les évite délibérément
- nextjs
Les Server Actions sont utiles, mais pas partout. Voici trois situations où nous choisissons délibérément de ne pas les utiliser, et pourquoi.
Server Actions : les 3 contextes où on les évite délibérément
Les Server Actions ont été vendues comme la solution aux mutations dans App Router. La réalité est plus nuancée. On les utilise, mais on a appris à identifier les cas où elles introduisent plus de problèmes qu'elles n'en résolvent.
Ce que les Server Actions font bien
Avant de parler des cas à éviter, soyons précis sur ce pour quoi elles sont réellement adaptées.
Les Server Actions brillent pour les mutations simples, couplées à une invalidation de cache via revalidatePath ou revalidateTag. Un formulaire de contact, une mise à jour de préférence utilisateur, un toggle d'état, ce sont leurs cas d'usage naturels.
"use server"
export async function updateUserPreference(formData: FormData) {
const theme = formData.get("theme")
await db.user.update({ where: { id: session.userId }, data: { theme } })
revalidatePath("/settings")
}Simple, colocalisé avec le formulaire, pas besoin d'une route API dédiée. C'est le sweet spot.
Contexte 1 : opérations longues ou incertaines
Une Server Action s'exécute dans le cycle de vie d'une requête HTTP. Si l'opération prend plus de quelques secondes, le navigateur attend, sans feedback intermédiaire possible, et sans mécanisme de retry natif.
On a eu le cas sur un traitement d'import CSV, 2 000 lignes, validation, insertion en base, envoi d'un email de confirmation. On avait commencé avec une Server Action. Résultat : timeout sur certains clients, UI bloquée, aucun moyen de reprendre une opération partiellement exécutée.
La bonne approche pour ce cas : une route API qui déclenche un job asynchrone (BullMQ, Inngest, ou même un simple worker Node), et un polling ou un webhook pour notifier l'état. La Server Action n'est pas le bon vecteur pour de l'asynchrone réel.
La règle qu'on suit : si l'opération peut dépasser 3 secondes dans des conditions normales, on ne passe pas par une Server Action.
Contexte 2 : les APIs consommées par plusieurs clients
Une Server Action est un endpoint implicite lié à un composant Next.js. Son contrat n'est pas versionné, sa signature n'est pas documentée, et elle n'est pas consommable directement par un client mobile, une extension, ou un service tiers.
Sur un projet avec une app mobile React Native en parallèle du site Next.js, on a vu des équipes tenter de partager des Server Actions. C'est techniquement possible en exposant l'endpoint généré, mais c'est fragile et non documenté par Vercel comme cas d'usage supporté.
Dès qu'une mutation doit être consommée par plus d'un client, on écrit une route API REST ou tRPC explicite. L'interface est claire, versionnable, testable en isolation.
// À éviter si la mutation est partagée
"use server"
export async function createOrder(data: OrderInput) { ... }
// Préféré : route API explicite
// app/api/orders/route.ts
export async function POST(request: Request) {
const data = await request.json()
// validation, traitement, réponse
}Contexte 3 : mutations critiques avec besoin d'audit
Les Server Actions n'ont pas de couche middleware standard. Ajouter de la journalisation, du rate limiting, de la gestion d'idempotence, ou une traçabilité fine demande des contournements non conventionnels.
Sur un back-office financier, on gérait des mutations sur des données sensibles : transferts, ajustements de solde, validations de documents. Chaque action devait être tracée avec l'IP, le user-agent, le contexte de session, et un identifiant d'idempotence pour éviter les doublons sur retry.
Implémenter tout ça dans des Server Actions est possible, mais ça revient à recréer une couche middleware à la main dans chaque fonction. Une route API avec un middleware Express-like (ou un wrapper custom Next.js) offre un point de contrôle unique et auditable.
Les Server Actions sont aussi exposées sans CSRF automatique dans certaines configurations, Next.js applique une protection par défaut via l'origine, mais elle ne couvre pas tous les cas cross-origin. Sur des mutations sensibles, on préfère contrôler explicitement.
Ce que ça ne veut pas dire
On n'est pas contre les Server Actions. Sur nos projets marketing, nos dashboards internes simples, nos formulaires classiques, on les utilise systématiquement. Elles réduisent la surface de code, évitent des routes API inutiles, et s'intègrent naturellement aux formulaires HTML natifs via l'attribut action.
<form action={updateUserPreference}>
<select name="theme">
<option value="light">Clair</option>
<option value="dark">Sombre</option>
</select>
<button type="submit">Enregistrer</button>
</form>Ce pattern, formulaire HTML natif + Server Action, fonctionne même sans JavaScript côté client. C'est une vraie amélioration par rapport à l'approche Pages Router.
L'arbitrage en pratique
Avant d'écrire une Server Action, on se pose trois questions :
- L'opération peut-elle prendre plus de 3 secondes ?
- Est-ce qu'un autre client que ce site Next.js en a besoin ?
- Est-ce qu'on a besoin d'audit, de rate limiting ou d'idempotence ?
Si la réponse à l'une des trois est oui, on écrit une route API. Sinon, la Server Action est probablement le bon choix.
La question qui reste ouverte : comment Next.js va-t-il gérer la composition de middlewares sur les Server Actions dans les versions futures ? C'est un manque réel pour les projets qui veulent un contrôle fin sans sortir du paradigme App Router.