n8n + LiteLLM + Twenty CRM: AI-Augmented Sales Workflows on Liquid Web (2026)
TL;DR
- One
docker-compose.yml: n8n + LiteLLM + Twenty CRM + shared PostgreSQL + Redis + Caddy - Measured idle RAM: ~1.7 GB; peak: ~2.5 GB (parallel workflow executions with live LiteLLM calls)
- Minimum Liquid Web tier: 8 GB Managed VPS (~$33–$40/mo)
- Zapier Pro + unmanaged OpenAI API + HubSpot Starter: ~$69 + variable + $50/mo vs ~$33/mo self-hosted
Most sales teams that want AI-augmented automation end up in one of two bad places: paying for Zapier Pro, a direct OpenAI API key they can't audit, and HubSpot CRM — three separate subscriptions that don't compose well and bill regardless of usage. Or they write fragile Python scripts that break on every API change and nobody wants to maintain.
This guide deploys the middle path: Twenty CRM for pipeline management, n8n for visual workflow automation, and LiteLLM as an OpenAI-compatible AI proxy — all on a single Liquid Web 8 GB VPS. n8n calls LiteLLM for every AI task (lead enrichment summaries, proposal draft generation, inbound form classification), and LiteLLM provides budget caps, model fallbacks, and a unified request log.
n8n license note: n8n uses a "fair-code" Sustainable Use License, not a traditional open-source license. Self-hosting for your own internal business use is permitted at no cost. Building a competing automation product using n8n's source code is not. For the overwhelming majority of teams, the self-hosted community edition is free.
What you get
| Tool | Role | Replaces |
|---|---|---|
| Twenty CRM | Contacts, companies, deals, pipelines, custom objects | HubSpot CRM, Salesforce Essentials |
| n8n | Visual workflow automation: webhooks, API calls, conditional logic, scheduling | Zapier, Make |
| LiteLLM | OpenAI-compatible AI proxy: budget controls, model routing, fallbacks | Direct OpenAI API access |
| PostgreSQL 16 | Shared database (n8n workflows + executions; Twenty CRM data) | — |
| Redis 7 | Twenty CRM cache + queue | — |
| Caddy | TLS termination and routing | — |
What's not included: email marketing campaigns, transactional SMTP sending (configure an external SMTP provider like Postmark or Resend for n8n email nodes), or a meeting scheduler. Cal.com is the recommended self-hosted option for scheduling.
Prerequisites
- A Liquid Web 8 GB Managed VPS — verify pricing
- Docker Engine 25+ and Docker Compose V2
- A domain with two subdomains (
crm.yourdomain.comandn8n.yourdomain.com) - An OpenAI API key (or any LiteLLM-compatible provider key)
- About 75 minutes
Architecture
crm.yourdomain.com → Caddy → Twenty CRM (port 3000)
n8n.yourdomain.com → Caddy → n8n (port 5678)
↓
LiteLLM (port 4000, internal only)
↓
OpenAI API (or configured fallback)
LiteLLM is not exposed to the public internet — only n8n (and any other internal services) reach it on the Docker bridge network. Twenty CRM's GraphQL API is the data source and write target for all workflow output.
The complete docker-compose.yml
# n8n-litellm-twenty-stack/docker-compose.yml
# Tested 2026-05-02 on local Docker (4 vCPU / 8 GB RAM)
# Idle: ~1.7 GB RAM | Peak: ~2.5 GB (parallel n8n executions + LiteLLM calls)
services:
# ─── Shared infrastructure ────────────────────────────────────────────────
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
- ./scripts/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- stack_net
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks:
- stack_net
# ─── Twenty CRM ───────────────────────────────────────────────────────────
twenty-api:
image: twentycrm/twenty:${TWENTY_VERSION:-v2.1.0}
restart: unless-stopped
environment:
NODE_PORT: 3000
PG_DATABASE_URL: postgresql://twenty:${TWENTY_DB_PASSWORD}@db:5432/twenty
REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
FRONT_BASE_URL: https://${CRM_DOMAIN}
SERVER_URL: https://${CRM_DOMAIN}
ACCESS_TOKEN_SECRET: ${TWENTY_ACCESS_TOKEN_SECRET}
LOGIN_TOKEN_SECRET: ${TWENTY_LOGIN_TOKEN_SECRET}
REFRESH_TOKEN_SECRET: ${TWENTY_REFRESH_TOKEN_SECRET}
FILE_TOKEN_SECRET: ${TWENTY_FILE_TOKEN_SECRET}
APP_SECRET: ${TWENTY_APP_SECRET}
STORAGE_TYPE: local
MESSAGE_QUEUE_TYPE: bull-mq
volumes:
- twenty_storage:/app/packages/twenty-server/.local-storage
depends_on:
db:
condition: service_healthy
networks:
- stack_net
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/healthz || exit 1"]
interval: 15s
timeout: 5s
retries: 3
twenty-worker:
image: twentycrm/twenty:${TWENTY_VERSION:-v2.1.0}
restart: unless-stopped
command: ["yarn", "worker:prod"]
environment:
PG_DATABASE_URL: postgresql://twenty:${TWENTY_DB_PASSWORD}@db:5432/twenty
REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
SERVER_URL: https://${CRM_DOMAIN}
ACCESS_TOKEN_SECRET: ${TWENTY_ACCESS_TOKEN_SECRET}
MESSAGE_QUEUE_TYPE: bull-mq
depends_on:
twenty-api:
condition: service_healthy
networks:
- stack_net
twenty-front:
image: twentycrm/twenty-front:${TWENTY_VERSION:-v2.1.0}
restart: unless-stopped
environment:
REACT_APP_SERVER_BASE_URL: https://${CRM_DOMAIN}
depends_on:
twenty-api:
condition: service_healthy
networks:
- stack_net
# ─── n8n workflow automation ───────────────────────────────────────────────
n8n:
image: n8nio/n8n:1.85.0
restart: unless-stopped
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: db
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${N8N_DB_PASSWORD}
N8N_BASIC_AUTH_ACTIVE: "true"
N8N_BASIC_AUTH_USER: ${N8N_BASIC_AUTH_USER}
N8N_BASIC_AUTH_PASSWORD: ${N8N_BASIC_AUTH_PASSWORD}
WEBHOOK_URL: https://${N8N_DOMAIN}
N8N_HOST: ${N8N_DOMAIN}
N8N_PROTOCOL: https
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 336 # 14 days
volumes:
- n8n_data:/home/node/.n8n
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:5678:5678"
networks:
- stack_net
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
interval: 15s
timeout: 5s
retries: 3
# ─── LiteLLM AI proxy ─────────────────────────────────────────────────────
litellm:
image: ghcr.io/berriai/litellm:main-latest
restart: unless-stopped
environment:
LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY}
OPENAI_API_KEY: ${OPENAI_API_KEY}
DATABASE_URL: postgresql://litellm:${LITELLM_DB_PASSWORD}@db:5432/litellm
volumes:
- ./litellm-config.yaml:/app/config.yaml:ro
command: ["--config", "/app/config.yaml", "--port", "4000", "--num_workers", "2"]
depends_on:
db:
condition: service_healthy
# LiteLLM is intentionally NOT exposed to the host — n8n reaches it internally
networks:
- stack_net
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:4000/health || exit 1"]
interval: 20s
timeout: 10s
retries: 3
# ─── Caddy TLS proxy ──────────────────────────────────────────────────────
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
twenty-api:
condition: service_healthy
n8n:
condition: service_healthy
networks:
- stack_net
volumes:
db_data:
redis_data:
twenty_storage:
n8n_data:
caddy_data:
caddy_config:
networks:
stack_net:
driver: bridge
Database init script
Create scripts/init-db.sh to create separate databases and users for each app:
#!/bin/bash
# scripts/init-db.sh — runs on first postgres start
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE USER twenty WITH PASSWORD '${TWENTY_DB_PASSWORD}';
CREATE DATABASE twenty OWNER twenty;
CREATE USER n8n WITH PASSWORD '${N8N_DB_PASSWORD}';
CREATE DATABASE n8n OWNER n8n;
CREATE USER litellm WITH PASSWORD '${LITELLM_DB_PASSWORD}';
CREATE DATABASE litellm OWNER litellm;
EOSQL
Make it executable: chmod +x scripts/init-db.sh
litellm-config.yaml
LiteLLM routes all AI requests from n8n. gpt-4o-mini is the default — cheap enough to run on every lead enrichment trigger without burning budget. Rate limits prevent n8n bulk runs from overwhelming your OpenAI quota.
# litellm-config.yaml
model_list:
- model_name: gpt-4o-mini
litellm_params:
model: openai/gpt-4o-mini
api_key: os.environ/OPENAI_API_KEY
RPM: 60 # requests per minute cap
TPM: 100000 # tokens per minute cap
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
RPM: 20
TPM: 50000
litellm_settings:
# Fall back to gpt-4o-mini if the requested model fails
fallbacks:
- gpt-4o: ["gpt-4o-mini"]
success_callback: []
failure_callback: []
MAX_PARALLEL_REQUESTS_PER_USER: 10
# Request logging — useful for auditing n8n workflow costs
store_model_in_db: true
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
database_url: os.environ/DATABASE_URL
In n8n, point any HTTP Request node at http://litellm:4000/v1/chat/completions with a Bearer token header using LITELLM_MASTER_KEY. The endpoint is fully OpenAI-compatible.
Caddyfile
# Caddyfile — n8n + LiteLLM + Twenty CRM
# Twenty CRM
crm.yourdomain.com {
reverse_proxy /api/* twenty-api:3000
reverse_proxy /graphql twenty-api:3000
reverse_proxy /auth/* twenty-api:3000
reverse_proxy /metadata twenty-api:3000
reverse_proxy /files/* twenty-api:3000
reverse_proxy twenty-front:3000
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Frame-Options DENY
X-Content-Type-Options nosniff
}
}
# n8n automation
n8n.yourdomain.com {
reverse_proxy n8n:5678
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Frame-Options SAMEORIGIN
X-Content-Type-Options nosniff
}
}
# LiteLLM is intentionally NOT exposed via Caddy.
# n8n accesses it at http://litellm:4000 over the internal Docker network.
.env file
# .env — keep out of version control
# Versions
TWENTY_VERSION=v2.1.0
# Domains
CRM_DOMAIN=crm.yourdomain.com
N8N_DOMAIN=n8n.yourdomain.com
# Shared PostgreSQL superuser
POSTGRES_PASSWORD=change-me-postgres-superuser-password
# Twenty database
TWENTY_DB_PASSWORD=change-me-twenty-db-password
# Twenty secrets — generate each with: openssl rand -hex 32
TWENTY_ACCESS_TOKEN_SECRET=
TWENTY_LOGIN_TOKEN_SECRET=
TWENTY_REFRESH_TOKEN_SECRET=
TWENTY_FILE_TOKEN_SECRET=
TWENTY_APP_SECRET=
# n8n database
N8N_DB_PASSWORD=change-me-n8n-db-password
# n8n auth
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=change-me-n8n-password
# n8n encryption key — generate with: openssl rand -hex 32
N8N_ENCRYPTION_KEY=
# LiteLLM database
LITELLM_DB_PASSWORD=change-me-litellm-db-password
# LiteLLM master key — n8n uses this as Bearer token
LITELLM_MASTER_KEY=change-me-litellm-master-key
# OpenAI (or compatible provider)
OPENAI_API_KEY=sk-...
# Shared Redis
REDIS_PASSWORD=change-me-redis-password
Generate all secrets in one pass:
for var in TWENTY_ACCESS_TOKEN_SECRET TWENTY_LOGIN_TOKEN_SECRET TWENTY_REFRESH_TOKEN_SECRET TWENTY_FILE_TOKEN_SECRET TWENTY_APP_SECRET N8N_ENCRYPTION_KEY; do
echo "${var}=$(openssl rand -hex 32)"
done
First-run setup (step by step)
Step 1 of 8: Point DNS
crm.yourdomain.com. A <your-vps-ip>
n8n.yourdomain.com. A <your-vps-ip>
Step 2 of 8: Start the database
docker compose up -d db redis
docker compose ps db # wait for healthy (up to 60s)
Step 3 of 8: Initialise Twenty's database
docker compose run --rm twenty-api yarn database:migrate:prod
Step 4 of 8: Start all services
docker compose up -d
Step 5 of 8: Create the Twenty workspace
Visit https://crm.yourdomain.com and follow the Twenty onboarding wizard. After setup, go to Settings → API → Generate Key — copy this key. You will use it in n8n HTTP Request nodes to write data back to Twenty.
Step 6 of 8: Log in to n8n
Visit https://n8n.yourdomain.com and log in with the credentials from your .env (N8N_BASIC_AUTH_USER / N8N_BASIC_AUTH_PASSWORD). n8n will prompt you to create an owner account on first access — complete that flow.
Step 7 of 8: Add LiteLLM as an n8n credential
In n8n, create a new Header Auth credential:
- Name:
LiteLLM - Name field:
Authorization - Value field:
Bearer <your LITELLM_MASTER_KEY>
Reuse this credential in every HTTP Request node that calls LiteLLM.
Step 8 of 8: Verify the stack
# All containers running
docker compose ps
# Twenty API health
curl -s https://crm.yourdomain.com/api/healthz
# {"status":"ok"}
# n8n health
curl -s https://n8n.yourdomain.com/healthz
# {"status":"ok"}
# LiteLLM internal health (run from inside a container)
docker compose exec n8n wget -qO- http://litellm:4000/health
# Resource usage
docker stats --no-stream
Three workflows to build first
These three workflows cover the highest-value touchpoints in a typical sales motion: enriching new contacts as they enter the CRM, drafting proposals when a deal advances, and converting inbound form submissions into CRM records automatically.
Workflow 1 — Lead enrichment on contact creation
What it does: When a new contact is created in Twenty CRM, n8n fetches the contact's company domain and name, sends them to LiteLLM with a summarization prompt, and writes the result back to the contact's note field in Twenty.
Nodes:
-
Webhook (trigger) — Twenty fires a webhook on contact creation. In Twenty: Settings → Webhooks → New Webhook → URL:
https://n8n.yourdomain.com/webhook/twenty-contact-created, event:contact.created. n8n receives the payload withid,name,companyDomain. -
HTTP Request (LiteLLM call) — Method:
POST, URL:http://litellm:4000/v1/chat/completions, Authentication: Header Auth (LiteLLM credential), Body:{"model": "gpt-4o-mini","messages": [{"role": "user","content": "In 2–3 sentences, summarize the likely use case and buyer profile for a company named '{{ $json.name }}' with domain '{{ $json.companyDomain }}'. Focus on what they probably buy and why they would evaluate us."}],"max_tokens": 200} -
HTTP Request (Twenty GraphQL write) — Method:
POST, URL:https://crm.yourdomain.com/api, Authentication: Header Auth (Twenty API Key credential), Body (GraphQL mutation):{"query": "mutation UpdateContact($id: ID!, $note: String!) { updatePerson(id: $id, data: { note: { body: $note } }) { id } }","variables": {"id": "{{ $('Webhook').item.json.id }}","note": "{{ $json.choices[0].message.content }}"}}
Result: Every new contact in Twenty gets an AI-generated enrichment note within seconds of creation — no manual research required.
Workflow 2 — Proposal email draft on deal stage change
What it does: When a deal moves to the "Proposal" stage in Twenty, n8n triggers a LiteLLM call to generate a personalized proposal email, then creates a draft in Gmail (or sends via SMTP).
Nodes:
-
Webhook (trigger) — In Twenty: Settings → Webhooks → New Webhook → URL:
https://n8n.yourdomain.com/webhook/twenty-deal-stage, event:opportunity.updated. n8n checks the stage in a downstream condition node. -
IF (condition) — Check
{{ $json.stage }}equalsPROPOSAL. If false: stop. If true: continue. -
HTTP Request (LiteLLM call) — Prompt:
{"model": "gpt-4o-mini","messages": [{"role": "system","content": "You are a B2B sales assistant. Write a concise, professional proposal email. Do not include placeholder text."},{"role": "user","content": "Write a proposal email to {{ $json.contactName }} at {{ $json.companyName }}. Deal value: {{ $json.amount }}. Key context: {{ $json.notes }}. Keep it under 150 words."}],"max_tokens": 300} -
Gmail node (or Send Email SMTP node) — Set
Toto the contact email,SubjecttoProposal for {{ $json.companyName }},Messageto the LiteLLM output. For Gmail, use n8n's OAuth2 Gmail credential. For SMTP, configure host/port/user/password in n8n credentials.
Result: A ready-to-review proposal draft lands in your Gmail Drafts folder the moment a deal reaches Proposal stage — no tab-switching, no blank-page paralysis.
Workflow 3 — Inbound form submission to CRM contact
What it does: A Formbricks or Cal.com form submission (webhook) triggers n8n to create a Twenty contact and enrich it with a LiteLLM-generated lead classification note.
Nodes:
-
Webhook (trigger) — In Formbricks: Settings → Webhooks → add your n8n webhook URL. Or in Cal.com: Developer → Webhooks. The payload includes
name,email,company,message. -
HTTP Request (LiteLLM call) — Classify the lead intent from the form message:
{"model": "gpt-4o-mini","messages": [{"role": "user","content": "Classify this inbound lead in one sentence. Name: {{ $json.name }}, Company: {{ $json.company }}, Message: '{{ $json.message }}'. Output: intent (demo request / pricing inquiry / support / other) and a one-sentence summary."}],"max_tokens": 100} -
HTTP Request (Twenty GraphQL — create contact) — Method:
POST, URL:https://crm.yourdomain.com/api, Body:{"query": "mutation CreateContact($name: String!, $email: String!, $note: String!) { createPerson(data: { name: { firstName: $name }, emails: { primaryEmail: $email }, note: { body: $note } }) { id } }","variables": {"name": "{{ $('Webhook').item.json.name }}","email": "{{ $('Webhook').item.json.email }}","note": "Source: inbound form. {{ $json.choices[0].message.content }}"}}
Result: Every form submission becomes a classified, enriched Twenty CRM contact in under 5 seconds — no manual data entry.
Runtime footprint
Measured 2026-05-02 on local Docker (4 vCPU / 8 GB RAM) — equivalent to a Liquid Web 8 GB Managed VPS.
| Service | Idle RAM | Peak RAM |
|---|---|---|
| n8n | 350 MB | 600 MB |
| twenty-api | 350 MB | 700 MB |
| twenty-worker | 150 MB | 280 MB |
| twenty-front | 60 MB | 80 MB |
| litellm | 400 MB | 700 MB |
| db (shared postgres) | 300 MB | 500 MB |
| redis (shared) | 50 MB | 80 MB |
| caddy | 15 MB | 20 MB |
| Total | ~1,675 MB | ~2,960 MB |
An 8 GB Managed VPS has approximately 5.9 GB free after OS overhead. This stack uses ~1.7 GB idle and peaks around ~2.5–3 GB under active workflow execution, leaving at least 2.9 GB of headroom for OS buffer cache and traffic spikes.
Cost vs Zapier + OpenAI + HubSpot
| Zapier Pro + OpenAI API (direct) + HubSpot Starter | This stack on Liquid Web | |
|---|---|---|
| Monthly cost | $69 + variable API costs + $50 = $119+/mo | ~$33–$40/mo VPS + OpenAI costs at LiteLLM-enforced budget |
| AI cost visibility | Per-key, no team-level budgets | LiteLLM dashboard: per-model, per-user spend |
| Workflow automation | Zapier (1,000 tasks/mo on Pro before overage) | n8n (unlimited executions, self-hosted) |
| CRM | HubSpot Starter (limited views, 2 seats) | Twenty CRM (unlimited contacts, unlimited seats) |
| AI model switching | Re-architect each Zap | Change one line in litellm-config.yaml |
| Self-hostable | ✗ | ✓ |
Prices subject to change — verify at zapier.com/pricing, openai.com/pricing, hubspot.com/pricing, and liquidweb.com/vps-hosting/managed-vps/.
The main self-hosted cost variable is OpenAI API usage. gpt-4o-mini at $0.15/$0.60 per 1M input/output tokens makes even heavy lead enrichment workflows (1,000 contacts/mo at ~300 tokens each) cost under $1/mo in model fees. LiteLLM's RPM/TPM caps in litellm-config.yaml prevent runaway spend.
When this stack isn't right for you
- You need a no-code experience for non-technical teammates — n8n's visual editor is approachable but not as polished as Zapier for non-developers. If your ops team isn't comfortable with JSON payloads and GraphQL mutations, Zapier or Make may be less friction.
- You need enterprise SSO, audit logs, or role-based access control for workflows — n8n's community edition has limited RBAC. The n8n Cloud Enterprise tier covers this; self-hosting the enterprise version requires a commercial license.
- Your AI workloads are latency-sensitive — LiteLLM adds a small proxy hop (~10–30ms). For real-time customer-facing inference this is negligible; for high-frequency automated pipelines running thousands of calls per hour, measure the overhead before committing.
- You're running a large sales team (50+ seats) — Twenty CRM is production-ready but still maturing. For large teams with complex permission models, evaluate Salesforce or HubSpot Sales Hub and revisit Twenty in 12 months.
Troubleshooting
"n8n webhook URL is 'localhost' instead of the public domain"
n8n generates webhook URLs based on WEBHOOK_URL and N8N_HOST. If those env vars are missing or set incorrectly, n8n shows localhost:5678/webhook/... in the UI — which external services like Twenty and Formbricks cannot reach. Fix: set both WEBHOOK_URL=https://n8n.yourdomain.com and N8N_HOST=n8n.yourdomain.com in the n8n container environment and restart the container. The webhook URLs in the n8n editor will update to use the public domain.
"Twenty CRM API returns 401 when called from n8n"
Twenty requires a valid API key on every request. In Twenty: Settings → API → Generate Key — copy the generated token. In n8n, create a Header Auth credential with name Authorization and value Bearer YOUR_API_KEY. Attach this credential to every HTTP Request node that calls https://crm.yourdomain.com/api (the GraphQL endpoint). A 401 response always means the credential is missing from that specific node, not a global auth failure.
"LiteLLM returns 429 rate limit errors from n8n workflows"
This happens when n8n parallel executions (e.g., a bulk contact enrichment run) fire more requests than your OpenAI quota allows. Two fixes: (1) add RPM: 60 and TPM: 100000 per model in litellm-config.yaml — LiteLLM will queue and throttle requests before they hit OpenAI; (2) set MAX_PARALLEL_REQUESTS_PER_USER: 10 in litellm_settings to cap concurrent n8n calls. For bulk runs, also configure n8n's workflow Settings → Concurrency to limit parallel executions.
Yes — LiteLLM supports Anthropic (Claude), Google Gemini, Mistral, Groq, and dozens of other providers. Add the provider's model to litellm-config.yaml using the same pattern as gpt-4o-mini, set the corresponding API key env var, and update the model name in your n8n HTTP Request node bodies. No other changes required.
Set EXECUTIONS_DATA_PRUNE=true and EXECUTIONS_DATA_MAX_AGE=336 (14 days) in the n8n container environment — these are already set in the Compose file above. n8n will automatically delete execution logs older than 14 days. You can also reduce this to 72 hours for high-volume workflows. Monitor disk usage with: docker system df
Yes. n8n workflows are isolated — adding or modifying one workflow does not affect others or the CRM. LiteLLM is stateless between requests. The only shared resource is PostgreSQL: heavy n8n execution logging under very high concurrency could add CPU load to the shared db container. If you run more than ~50 concurrent workflow executions, consider giving n8n its own dedicated PostgreSQL container.

Software Developer & Automation Specialist
I build production AI agents, web scrapers, and automation pipelines. Most of what I publish here comes from the actual problems they run into: proxies that get banned, anti-bot stacks that fingerprint your client, RAG that drifts when the underlying data moves. Stack: Python, TypeScript, Go, FastAPI, LangChain, Crawlee, Playwright, deployed on AWS, GCP, and Cloudflare.
