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ò.

Cover for n8n no hauria de substituir tot el teu backend

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:

  1. Fase lluna de mel. Muntes un workflow ràpid, funciona, tothom content. “Mira, sense escriure codi.”
  2. Fase expansió. Comences a afegir lògica. Condicionals, bucles, transformacions. El workflow creix. Segueix funcionant.
  3. 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:

  1. Identifica la lògica de negoci dins del workflow. Normalment és un node Function o un bloc de nodes amb condicionals.
  2. Mou aquesta lògica a un servei (FastAPI si el teu stack és Python, Spring Boot si és JVM).
  3. 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

AspecteWorkflow n8nAPI pròpia
Velocitat de prototipatMolt altaMitjana
Facilitat de mantenimentBaixa si hi ha lògica complexaAlta amb bones pràctiques
TestingNo hi ha framework integratUnit tests, integration tests, CI/CD
DebuggingNode per node, visualLogs, stack traces, breakpoints
VersionatJSON diffs il·legiblesGit diffs clars
Code reviewMolt difícilEstàndard
EscalabilitatLimitadaSegons el teu disseny
Corba d’aprenentatgeBaixa al principiMitjana-alta
IntegracionsCentenars de nodes llestosTu les implementes
Cost de desenvolupamentBaix per a fluxos simplesMajor inversió inicial
Dependència de l’einaAlta (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.

OshyTech

Enginyeria backend i de dades orientada a sistemes escalables, automatització i IA.

Navegació

Copyright 2026 OshyTech. Tots els drets reservats