const { Worker } = require('bullmq');
const Redis = require('ioredis');
const connection = new Redis(process.env.REDIS_URL);
// Rulează ca un proces de fundal stabil, fără limitări de serverless
const worker = new Worker('pdf-generation', async (job) => {
console.log(`Procesez PDF-ul pentru userul: ${job.data.userId}`);
// Logica grea de generat PDF-uri
await generateHeavyPdf(job.data);
}, { connection });
worker.on('completed', (job) => {
console.log(`Job ${job.id} finalizat cu succes!`);
});Am văzut tot mai des tendința de a pune absolut totul în API routes din Next.js, doar pentru că "e la îndemână". E o greșeală de arhitectură care te va costa performanță și nopți pierdute cu debugging-ul. Azi vorbim exact despre momentele în care un server Node.js clasic (Express, Fastify sau chiar NestJS) bate Next.js la fundul gol.
Cazul clasic: Job-uri lungi și parsare de fișiere
La un proiect trecut cu vreo 8k utilizatori activi, aveam de procesat lunar niște fișiere Excel masive pentru facturare. Inițial, un coleg le-a trântit într-un API route în Next.js, rulat pe Vercel.
Evident, am dat direct cu capul de pragul de timeout (care e de vreo 15 secunde pe planul Hobby și maxim 5 minute pe Enterprise). Ca să nu mai zic de cold starts. Soluția? Am mutat logica de parsare pe un VPS de 5$ în Hetzner, rulând un server simplu de Fastify sub PM2. Am economisit cam 30% la build time pe frontend și am scăpat definitiv de timeout-uri.
WebSockets și conexiuni persistente
Dacă ai nevoie de chat în timp real, notificări push instant sau colaborare live, Next.js nu e făcut pentru asta. Serverless-ul prin definiție e efemer: pornește, își face treaba, moare. Nu poți ține o conexiune deschisă de WebSocket (cum e Socket.io) pe o funcție lambda fără să rulezi facturi uriașe sau să pierzi conexiunile la fiecare deploy.
Un server de Node.js simplu rezolvă problema elegant. Ții conexiunile deschise, faci pub/sub prin Redis și lași Next.js-ul să se ocupe doar de ce știe el mai bine: randat pagini și făcut SEO.
Microservicii și Job Processors (BullMQ)
Dacă ai nevoie de un worker care să asculte o coadă de mesaje din Redis sau RabbitMQ, nu-l pune în Next.js. Am văzut hack-uri cu obiectul global în Next pentru a inițializa clienți de Redis care să nu se recreeze la fiecare hot-reload în development. E o mizerie care crapă des în producție.
Un server Node chior, pornit cu node worker.js, este perfect pentru un job processor cu BullMQ. Scrii câteva linii de cod, îl pui în PM2 să ruleze pe fundal și ai terminat povestea.
Trade-off-ul sincer
Să fim realiști. Dacă ai o aplicație mică, un SaaS de weekend unde doar salvezi un user în baza de date și trimiți un email, Next.js e perfect. Nu te complica cu infrastructură separată.
Mai jos am lăsat un exemplu rapid de cum ar trebui să arate un worker curat de Node, rulat complet separat de aplicația ta de Next.js.
Voi cum faceți? Încă mai împingeți limitele din Next.js cu hack-uri de timeout sau ați spart deja backend-ul în microservicii de Node?