n8n no hauria de substituir tot el teu backend
Límits d'eines low-code com n8n: quan automatitzar i quan escriure programari de debò.

Fa uns mesos vaig veure una cosa que em va preocupar. Un equip havia construït tota la seva lògica de negoci dins de n8n. No parlo d’enviar emails quan algú es registra o de sincronitzar dades entre dos serveis. Parlo de validació de comandes, càlcul de preus amb descomptes escalonats, gestió d’estats d’enviament i generació de factures. Tot en workflows visuals amb desenes de nodes, condicionals imbricats i funcions JavaScript inline. Quan alguna cosa fallava, ningú sabia on mirar. Quan necessitaven canviar una regla de negoci, tocaven tres workflows diferents i resaven per no trencar els altres.
n8n és una eina excel·lent per al que va ser dissenyada: automatitzar integracions, connectar serveis i executar fluxos que d’altra manera serien glue code repetitiu. Però no és un framework de desenvolupament de programari. I tractar-la com a tal té conseqüències que apareixen tard, quan ja fan mal.
El problema no és n8n, és on el poses
Vull ser clar des del principi: no estic en contra de n8n ni del low-code en general. El faig servir cada dia per a automatitzacions que m’estalvien hores de feina. El problema apareix quan l’eina es converteix en el sistema complet en lloc de ser una peça del sistema.
El low-code funciona millor com a cola entre sistemes que com a fonament d’una aplicació.
He vist aquest patró repetir-se en tres fases:
- Fase lluna de mel. Muntes un workflow ràpid, funciona, tothom content. “Mira, sense escriure codi.”
- Fase expansió. Comences a afegir lògica. Condicionals, bucles, transformacions. El workflow creix. Segueix funcionant.
- Fase dolor. El workflow té 60 nodes. Ningú recorda per què hi ha un IF al node 23. Un canvi a l’API externa trenca tres branques. No hi ha tests. No hi ha logs clars. El debugging és fer clic a cada node per veure què ha sortit.
Regles de decisió: quan n8n, quan codi
Després de fer servir n8n durant bastant de temps i haver-me equivocat més d’un cop, tinc un conjunt de criteris que aplico abans de decidir si alguna cosa va en un workflow o en codi propi.
Va a n8n quan…
- És glue code. Connectar servei A amb servei B. Rebre un webhook i reenviar dades transformades. Sincronitzar un CRM amb una base de dades.
- La lògica és lineal o té poques branques. Si pots descriure el flux en una frase (“quan arriba una comanda, envia un email i actualitza el CRM”), probablement encaixa en un workflow.
- No necessita tests unitaris. Si la lògica és tan simple que un test seria trivial, un workflow és suficient.
- El manteniment el pot fer algú que no és programador. Si vols que màrqueting pugui canviar el text d’una notificació sense demanar-ho a desenvolupament.
- És un prototip. Estàs validant una idea. Si funciona, ja l’extrauràs a codi.
Va a codi quan…
- Hi ha lògica de negoci complexa. Càlculs amb regles que depenen de múltiples condicions, estats, configuracions.
- Necessites tests. Si una regla mal implementada pot causar un problema de negoci, necessites tests automatitzats. A n8n no hi ha framework de testing integrat.
- Hi ha concurrència o estat. Múltiples processos accedint a les mateixes dades, race conditions, transaccions que han de ser atòmiques.
- El flux té més de 15-20 nodes amb condicionals. És un senyal clar que la complexitat ha superat el que un workflow visual pot gestionar de forma llegible.
- Necessites versionat i code review. Els workflows de n8n es poden exportar com a JSON, però fer diff de dos JSONs de 500 línies en un PR no és el mateix que revisar codi.
Exemples concrets
Exemple 1: Notificació de nou registre (n8n)
Un usuari es registra a la teva app. Vols enviar un email de benvinguda i notificar l’equip per Slack.
Això és textbook n8n. Flux lineal, sense lògica complexa, integracions estàndard.
Webhook (nou usuari)
→ Enviar email de benvinguda (SendGrid)
→ Notificar a Slack (#nous-usuaris)
→ Guardar a Google Sheets (registre d'onboarding)No té sentit escriure un servei per a això. n8n ho resol en 10 minuts.
Exemple 2: Càlcul de preus amb descomptes (API pròpia)
El preu final d’una comanda depèn de: tipus de client, volum de la comanda, promocions actives, descomptes per fidelitat, impostos per regió, i regles d’enviament gratuït que canvien cada mes.
Això NO hauria d’estar a n8n. Les raons:
# pricing_service.py - FastAPI
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from decimal import Decimal
app = FastAPI()
class OrderRequest(BaseModel):
customer_id: str
items: list[dict]
region: str
promo_code: str | None = None
class PricingResult(BaseModel):
subtotal: Decimal
discount: Decimal
tax: Decimal
shipping: Decimal
total: Decimal
rules_applied: list[str]
@app.post("/calculate-price", response_model=PricingResult)
def calculate_price(order: OrderRequest):
customer = get_customer(order.customer_id)
subtotal = sum_items(order.items)
# Reglas de descuento
discount = Decimal("0")
rules = []
# Descuento por volumen
if subtotal > Decimal("500"):
discount += subtotal * Decimal("0.05")
rules.append("volume_5pct")
# Descuento por fidelidad
if customer.loyalty_tier == "gold":
discount += subtotal * Decimal("0.10")
rules.append("loyalty_gold_10pct")
# Promoción activa
if order.promo_code:
promo_discount = apply_promo(order.promo_code, subtotal)
discount += promo_discount
rules.append(f"promo_{order.promo_code}")
# Impuestos por región
tax = calculate_tax(subtotal - discount, order.region)
# Envío gratuito
shipping = Decimal("0") if (subtotal - discount) > Decimal("100") else Decimal("4.99")
if shipping == Decimal("0"):
rules.append("free_shipping")
return PricingResult(
subtotal=subtotal,
discount=discount,
tax=tax,
shipping=shipping,
total=subtotal - discount + tax + shipping,
rules_applied=rules,
)Això té tests, versionat, logs, i es pot revisar en un PR. Si una regla canvia, saps exactament on tocar.
Exemple 3: Sincronització d’inventari (depèn)
Cada hora necessites llegir l’inventari d’un ERP i actualitzar una base de dades que consulta la teva app.
Si la sincronització és directa (llegir, transformar lleugerament, escriure), n8n val. Si la sincronització té regles de conflicte, prioritats entre fonts, o lògica de reconciliació, millor un script o servei.
Els riscos de posar lògica complexa en workflows
Debugging
Quan un workflow de n8n falla, la forma d’investigar és anar node per node veient quines dades van entrar i quines dades van sortir. No hi ha stack traces clars. No hi ha breakpoints. No hi ha logging estructurat. Per a un flux de 5 nodes és gestionable. Per a un de 40 nodes amb branques condicionals, és un infern.
Testing
n8n no té un framework de testing. No pots escriure unit tests per a la lògica d’un node. No pots fer mocking de serveis externs. No pots executar una suite de tests en CI/CD abans de desplegar un canvi. Si la teva lògica de negoci està a n8n, no té tests. Així de simple.
Versionat
Els workflows s’exporten com a JSON. Pots ficar-los a git, però:
- Els diffs són enormes i il·legibles.
- No hi ha eina de merge que entengui l’estructura d’un workflow.
- Un canvi cosmètic (moure un node de posició al canvas) genera un diff que oculta el canvi real.
{
"nodes": [
{
"parameters": {
"functionCode": "const items = $input.all();\n// 47 líneas de JavaScript..."
},
"name": "Calculate Price",
"type": "n8n-nodes-base.function",
"position": [820, 340]
}
]
}Revisar això en un PR és molt diferent de revisar un arxiu Python amb funcions ben anomenades.
Dependència de persones
Quan la lògica està en codi, qualsevol desenvolupador pot entendre-la llegint l’arxiu. Quan està en un workflow visual, necessites obrir n8n, navegar pels nodes, entendre les connexions, i sovint interpretar JavaScript inline escrit de forma compacta. La corba d’aprenentatge per mantenir un workflow complex és més alta del que sembla.
Quan extreure a una API pròpia
Si ja tens lògica complexa a n8n i estàs patint algun dels problemes que he descrit, el patró d’extracció que millor em funciona és:
- Identifica la lògica de negoci dins del workflow. Normalment és un node Function o un bloc de nodes amb condicionals.
- Mou aquesta lògica a un servei (FastAPI si el teu stack és Python, Spring Boot si és JVM).
- El workflow de n8n crida al teu servei per HTTP. n8n es queda com a orquestrador, no com a motor de lògica.
Abans:
Webhook → [40 nodes de lògica a n8n] → Resposta
Després:
Webhook → HTTP Request a la teva API → Resposta
(la lògica està al teu servei, amb tests i versionat)Aquest patró manté l’avantatge de n8n (orquestració visual, integracions fàcils) sense els seus desavantatges (debugging, testing, versionat de lògica).
Taula comparativa: workflow n8n vs API pròpia
| Aspecte | Workflow n8n | API pròpia |
|---|---|---|
| Velocitat de prototipat | Molt alta | Mitjana |
| Facilitat de manteniment | Baixa si hi ha lògica complexa | Alta amb bones pràctiques |
| Testing | No hi ha framework integrat | Unit tests, integration tests, CI/CD |
| Debugging | Node per node, visual | Logs, stack traces, breakpoints |
| Versionat | JSON diffs il·legibles | Git diffs clars |
| Code review | Molt difícil | Estàndard |
| Escalabilitat | Limitada | Segons el teu disseny |
| Corba d’aprenentatge | Baixa al principi | Mitjana-alta |
| Integracions | Centenars de nodes llestos | Tu les implementes |
| Cost de desenvolupament | Baix per a fluxos simples | Major inversió inicial |
| Dependència de l’eina | Alta (vendor lock-in visual) | Baixa (codi estàndard) |
Quan mantenir a n8n
No tot necessita extreure’s a codi. Aquestes són les tasques que mantinc a n8n sense remordiments:
- Notificacions. Emails, Slack, Telegram. Fluxos lineals, sense lògica de negoci.
- Sincronització simple de dades. Llegir d’una API, transformar un parell de camps, escriure a una altra.
- Webhooks de pas. Rebre un event i reenviar-lo a un altre servei amb format diferent.
- Tasques programades simples. Cada dilluns a les 9, exportar un CSV de la base de dades i enviar-lo per email.
- Prototips. Validar una idea d’integració abans d’invertir en codi.
Si pots descriure el que fa el teu workflow en una frase de menys de 20 paraules, probablement està bé a n8n. Si necessites un paràgraf, probablement no.
El patró que em funciona
La meva arquitectura actual amb n8n segueix aquest principi: n8n orquestra, el codi decideix.
┌──────────────┐
│ n8n │
│ (orquestrador)│
└──────┬───────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌──────────┐
│ FastAPI │ │ Serveis │ │ Bases de │
│ (lògica) │ │ externs │ │ dades │
└────────────┘ └────────────┘ └──────────┘n8n rep events, programa execucions i connecta serveis. Quan hi ha una decisió de negoci, crida a una API que té la lògica, els tests i el versionat que necessita. El millor dels dos mons.
El que no vull que entenguis malament
Aquest article no és una crítica a n8n. És una crítica a fer-lo servir per al que no està dissenyat. És com fer servir Excel com a base de dades: funciona fins que no funciona, i quan deixa de funcionar fa molt mal.
n8n és una eina fantàstica en el seu domini. He muntat automatitzacions amb n8n que m’haurien costat dies de desenvolupament si les hagués escrit en codi. La clau és saber quan estàs automatitzant i quan estàs programant. Si estàs programant, fes servir eines de programació.
La propera vegada que et trobis escrivint una funció de 50 línies de JavaScript dins d’un node Function de n8n, para un moment i pregunta’t: “Això hauria d’estar aquí?”. Si la resposta no és un sí immediat, probablement sigui el moment d’obrir el teu IDE.


