instruction: What's wrong with this n8n workflow that keeps running forever?

output:
**Anti-Pattern: Infinite Loop Detection**

The workflow creates an infinite loop because a webhook triggers itself:

```
Webhook → HTTP Request (calls same webhook URL) → Webhook triggers again
```

**Why It's Bad:**
- Consumes all available executions
- Can crash the n8n instance
- May exceed API rate limits
- Uses memory until system fails

**How to Fix:**
1. Add a loop counter in workflow data
2. Use IF node to check counter before HTTP call
3. Add unique execution ID to prevent re-triggering
4. Use a Set node to track processed items

```javascript
// In Code node - add loop protection
const MAX_ITERATIONS = 10;
const currentCount = $input.first().json.loopCount || 0;

if (currentCount >= MAX_ITERATIONS) {
  throw new Error('Loop limit reached');
}

return { loopCount: currentCount + 1 };
```

severity: critical


instruction: Why is my n8n workflow using too much memory?

output:
**Anti-Pattern: Memory Leak in Workflow**

Common causes of memory issues in n8n:

**1. Loading Entire Datasets**
```javascript
// BAD: Loads everything into memory
const allRecords = await getAll(); // 1 million rows
```

**Solution: Use pagination**
```javascript
// GOOD: Process in batches
const batchSize = 100;
for (let offset = 0; ; offset += batchSize) {
  const batch = await getPage(offset, batchSize);
  if (batch.length === 0) break;
  // Process batch
}
```

**2. Not Cleaning Up Binary Data**
```javascript
// BAD: Retaining binary data through workflow
return items; // Carries all attachments forward
```

**Solution: Drop binary when not needed**
```javascript
// GOOD: Remove binary data after processing
return items.map(item => ({
  json: item.json,
  binary: {} // Clear binary
}));
```

**3. Using Item Lists node without limits**
- Always set a maximum limit
- Use Split In Batches to process chunks
- Enable 'Execute Once' when possible

severity: high


instruction: What security mistakes should I avoid in n8n workflows?

output:
**Security Anti-Patterns in n8n**

**1. Hardcoded Credentials (CRITICAL)**
```javascript
// NEVER DO THIS
const apiKey = "sk-live-abc123def456";
```

**Fix: Use n8n Credentials**
- Create credential in n8n UI
- Reference via credential node parameter
- Credentials are encrypted at rest

**2. Exposing Sensitive Data in Logs**
```javascript
// BAD: Logs contain secrets
console.log('Request:', JSON.stringify(requestWithApiKey));
```

**Fix: Sanitize before logging**
```javascript
const sanitized = { ...request, apiKey: '[REDACTED]' };
console.log('Request:', JSON.stringify(sanitized));
```

**3. No Webhook Authentication**
```javascript
// BAD: Public webhook anyone can call
// Webhook → Process sensitive data
```

**Fix: Add authentication**
- Enable 'Authentication' in webhook node
- Use Header Auth with secret key
- Validate IP whitelist in Code node

**4. SQL Injection Vulnerability**
```javascript
// BAD: Direct string interpolation
const query = `SELECT * FROM users WHERE id = ${userId}`;
```

**Fix: Use parameterized queries**
```javascript
const query = 'SELECT * FROM users WHERE id = $1';
const params = [userId];
```

type: security


instruction: How do I prevent API abuse in my n8n workflows?

output:
**Preventing API Abuse in n8n**

**1. Rate Limiting Pattern**
```javascript
// Add rate limiting in Code node
const RATE_LIMIT = 10; // requests per minute
const cacheKey = `rate_limit_${$input.first().json.clientId}`;

// Check Redis/memory for rate count
const currentCount = await getFromCache(cacheKey) || 0;
if (currentCount >= RATE_LIMIT) {
  throw new Error('Rate limit exceeded. Try again in 1 minute.');
}

await setInCache(cacheKey, currentCount + 1, 60); // TTL 60 seconds
```

**2. Input Validation**
```javascript
// Validate all webhook inputs
const { email, amount } = $input.first().json;

if (!email || !email.includes('@')) {
  throw new Error('Invalid email format');
}

if (typeof amount !== 'number' || amount < 0 || amount > 10000) {
  throw new Error('Invalid amount: must be 0-10000');
}
```

**3. Request Size Limits**
- Set max body size in n8n config
- Validate file sizes before processing
- Reject oversized payloads early

**4. Timeout Protection**
- Set execution timeout in workflow settings
- Add timeout to HTTP Request nodes
- Use circuit breaker pattern for external APIs


instruction: What performance mistakes slow down n8n workflows?

output:
**Performance Anti-Patterns in n8n**

**1. Synchronous Processing of Large Lists**
```javascript
// BAD: Processes 10,000 items sequentially
for (const item of items) {
  await processItem(item); // Waits for each
}
```

**Fix: Use batching and parallelism**
- Split In Batches node (set batch size 50-100)
- Enable 'Continue On Fail' to not block on errors

**2. No Caching for Repeated Lookups**
```javascript
// BAD: Fetches same config for every item
for (const item of items) {
  const config = await fetchConfig(); // Same every time!
}
```

**Fix: Cache common data**
```javascript
// Fetch once, reuse
const config = await fetchConfig();
return items.map(item => ({
  ...item,
  config
}));
```

**3. Fetching Unnecessary Fields**
```javascript
// BAD: Gets entire object when only need ID
const users = await getUsers(); // Returns 50 fields each
const ids = users.map(u => u.id); // Only using 1 field
```

**Fix: Use API field selection**
```javascript
const users = await getUsers({ fields: 'id' });
```

**4. Not Using Pagination**
```javascript
// BAD: Tries to load all records
const allOrders = await api.getOrders(); // 1 million records
```

**Fix: Stream with pagination**
```javascript
let page = 1;
while (true) {
  const orders = await api.getOrders({ page, limit: 100 });
  if (!orders.length) break;
  yield orders; // Process page
  page++;
}
```

type: performance

severity: medium


instruction: What architecture mistakes should I avoid when building n8n workflows?

output:
**Architecture Anti-Patterns in n8n**

**1. Monolithic Mega-Workflows**
- Single workflow with 100+ nodes
- Hard to debug, maintain, or modify
- One failure crashes everything

**Fix: Decompose into sub-workflows**
```
Main Workflow
  → Execute Workflow: Fetch Data
  → Execute Workflow: Transform Data
  → Execute Workflow: Send Notifications
```

**2. Tight Coupling to External Services**
```javascript
// BAD: Direct calls everywhere
await sendgrid.send(email);
await sendgrid.send(email2);
await sendgrid.send(email3);
```

**Fix: Abstract through wrapper nodes**
- Create reusable sub-workflow for email
- Easy to swap providers later
- Single place to add logging/retry

**3. No Error Handling Strategy**
```
Start → Fetch → Transform → Save
// If Transform fails, entire workflow fails
```

**Fix: Add error boundaries**
```
Start → Fetch → Error Trigger attached
                   ↓
              Transform → Error Trigger attached
                            ↓
                         Save → Success notification
```

**4. Hardcoded Business Logic**
```javascript
// BAD: Magic numbers in code
if (order.total > 500) { // Why 500?
  applyDiscount(0.1); // Why 10%?
}
```

**Fix: Externalize configuration**
- Store thresholds in database
- Use environment variables
- Create config sub-workflow

type: architecture


instruction: How do I handle 'ECONNREFUSED' errors in n8n HTTP requests?

output:
**Troubleshooting ECONNREFUSED in n8n**

This error means the target server refused the connection.

**Common Causes & Fixes:**

**1. Service Not Running**
```bash
# Check if service is running
curl http://localhost:3000/health
# If fails, start the service
docker-compose up -d
```

**2. Incorrect URL/Port**
- Verify the URL in HTTP Request node
- Check port number matches service config
- Use internal Docker network names if in containers

**3. Firewall Blocking**
```bash
# Check firewall rules
sudo ufw status
# Allow the port
sudo ufw allow 3000
```

**4. n8n in Docker Can't Reach localhost**
```yaml
# docker-compose.yml fix
services:
  n8n:
    extra_hosts:
      - "host.docker.internal:host-gateway"
```
Then use `http://host.docker.internal:3000` instead of `localhost`

**5. Retry Strategy**
```javascript
// Add retry logic in Code node
const maxRetries = 3;
for (let i = 0; i < maxRetries; i++) {
  try {
    return await makeRequest();
  } catch (e) {
    if (i === maxRetries - 1) throw e;
    await sleep(1000 * Math.pow(2, i)); // Exponential backoff
  }
}
```

topic: troubleshooting

error_type: connection


instruction: How do I debug '401 Unauthorized' errors in n8n?

output:
**Debugging 401 Unauthorized in n8n**

**Step 1: Verify Credentials**
- Go to Credentials tab
- Edit the credential and test connection
- Check if API key/token is expired

**Step 2: Check Authentication Method**
| API Expects | n8n Setting |
|-------------|-------------|
| Bearer Token | Header Auth with 'Authorization: Bearer xxx' |
| API Key Header | Header Auth with 'X-API-Key: xxx' |
| Basic Auth | Credential type: HTTP Basic Auth |
| OAuth2 | Credential type: OAuth2 API |

**Step 3: Verify Headers**
```javascript
// In HTTP Request node, check these settings:
{
  "headerParameters": {
    "Authorization": "Bearer {{$credentials.apiKey}}"
  }
}
```

**Step 4: Test Outside n8n**
```bash
# Verify API works with curl
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.example.com/endpoint
```

**Step 5: Common Fixes**
- Regenerate API key if expired
- Check if using test vs production keys
- Verify OAuth scopes include required permissions
- Check if IP whitelist is blocking n8n server

**Step 6: Debug Mode**
```javascript
// Add to Code node to see actual request
console.log('Request headers:', $request.headers);
console.log('Auth config:', $credentials);
```

error_type: auth


instruction: How do I handle rate limiting errors (429) in n8n?

output:
**Handling Rate Limits (429 Too Many Requests) in n8n**

**1. Enable Built-in Retry**
In HTTP Request node settings:
- Enable 'Retry On Fail'
- Set 'Max Retries': 3
- Set 'Wait Between Retries': 1000ms

**2. Implement Exponential Backoff**
```javascript
// Code node with smart retry
async function withBackoff(fn, maxRetries = 5) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.response?.status !== 429) throw error;

      // Get retry-after header or calculate
      const retryAfter = error.response.headers['retry-after'];
      const waitTime = retryAfter
        ? parseInt(retryAfter) * 1000
        : Math.pow(2, i) * 1000;

      console.log(`Rate limited. Waiting ${waitTime}ms`);
      await new Promise(r => setTimeout(r, waitTime));
    }
  }
  throw new Error('Max retries exceeded');
}
```

**3. Add Rate Limiting to Workflow**
- Use 'Split In Batches' with 'Wait Between Batches'
- Set batch time based on API limits (e.g., 1000ms for 60/min)

**4. Queue-Based Processing**
```
Webhook → Add to Queue (Redis/Database)

Separate workflow:
Schedule (every minute) → Get 50 from Queue → Process → Mark Complete
```

**5. Monitor and Alert**
- Log rate limit occurrences
- Set up alerting when rate limits spike
- Consider upgrading API tier if consistently hitting limits


instruction: How do I debug 'undefined' or null values in n8n expressions?

output:
**Debugging Undefined/Null Values in n8n Expressions**

**1. Use Expression Editor Debug Mode**
Click the expression field, use the built-in preview to see actual values.

**2. Safe Property Access**
```javascript
// BAD: Crashes if customer is undefined
{{ $json.customer.email }}

// GOOD: Safe navigation
{{ $json.customer?.email ?? 'no-email@example.com' }}

// GOOD: With fallback
{{ $json.customer?.email || 'default@email.com' }}
```

**3. Add Debug Code Node**
```javascript
// Insert after problematic node
console.log('Full input:', JSON.stringify($input.all(), null, 2));
console.log('First item json:', $input.first().json);
console.log('Target field:', $input.first().json.customer);

return $input.all();
```

**4. Check Data Flow**
- Add 'Execution Data' view in workflow
- Click each node to see output
- Verify previous node is outputting expected structure

**5. Common Causes**
| Symptom | Likely Cause |
|---------|--------------|
| `undefined` | Field name typo or missing field |
| `null` | API returned null value |
| `[object Object]` | Need to access nested property |
| Empty string | Field exists but has no value |

**6. Defensive Code Pattern**
```javascript
const data = $input.first().json;

// Validate required fields
const required = ['email', 'name', 'orderId'];
for (const field of required) {
  if (!data[field]) {
    throw new Error(`Missing required field: ${field}`);
  }
}
```


instruction: How do I handle timeout errors in n8n?

output:
**Handling Timeout Errors in n8n**

**1. Increase Node-Level Timeout**
In HTTP Request node:
- Settings → Timeout: 60000 (60 seconds)

**2. Increase Workflow Execution Timeout**
```bash
# Environment variable
EXECUTIONS_TIMEOUT=600  # 10 minutes
EXECUTIONS_TIMEOUT_MAX=3600  # Max 1 hour
```

**3. Handle Long Operations Asynchronously**
```
Start → Trigger long job (returns job ID)
     → Wait node (30 seconds)
     → Poll job status
     → IF complete → Continue
        ELSE → Loop back to Wait
```

**4. Implement Timeout Wrapper**
```javascript
// Code node with timeout protection
async function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Operation timed out')), ms)
  );
  return Promise.race([promise, timeout]);
}

try {
  const result = await withTimeout(
    $http.request({ url: 'https://slow-api.com/data' }),
    30000 // 30 second timeout
  );
  return { result };
} catch (e) {
  return { error: e.message, fallback: true };
}
```

**5. Chunk Large Operations**
Instead of processing 10,000 items at once:
```
Split In Batches (100 items) → Process → Merge results
```

**6. Use Webhook Callbacks for Long Jobs**
```
Request → Start external job with callback URL
         → Return immediately

Webhook listens → Job complete callback → Continue processing
```

error_type: timeout


instruction: How do I build multi-tenant workflows in n8n?

output:
**Multi-Tenant Architecture in n8n**

**1. Tenant Identification**
```javascript
// Extract tenant from request
const tenantId = $input.first().json.headers['x-tenant-id']
  || $input.first().json.subdomain
  || 'default';

// Validate tenant
const validTenants = await getTenantList();
if (!validTenants.includes(tenantId)) {
  throw new Error('Invalid tenant');
}

return { tenantId, ...inputData };
```

**2. Tenant-Specific Credentials**
```javascript
// Store credentials per tenant in database
const tenantConfig = await db.query(
  'SELECT api_key, webhook_url FROM tenant_config WHERE id = $1',
  [tenantId]
);

// Use tenant-specific settings
return {
  apiKey: tenantConfig.api_key,
  webhookUrl: tenantConfig.webhook_url
};
```

**3. Data Isolation Pattern**
```javascript
// Always filter by tenant
const orders = await db.query(
  'SELECT * FROM orders WHERE tenant_id = $1 AND status = $2',
  [tenantId, 'pending']
);

// Never return data without tenant filter
```

**4. Workflow Per Tenant (Enterprise)**
```
Main Router Workflow
  → Switch node on tenantId
  → Execute Workflow: tenant_a_customizations
  → Execute Workflow: tenant_b_customizations
  → Common post-processing
```

**5. Audit Logging**
```javascript
// Log all operations with tenant context
await logAudit({
  tenantId,
  action: 'order_created',
  userId: $input.first().json.userId,
  timestamp: new Date().toISOString(),
  details: { orderId }
});
```

topic: enterprise

complexity: advanced


instruction: How do I set up high-availability n8n in production?

output:
**High-Availability n8n Architecture**

**1. Multi-Instance Setup**
```yaml
# docker-compose-ha.yml
services:
  n8n-main:
    image: n8nio/n8n
    environment:
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
    deploy:
      replicas: 2

  n8n-worker:
    image: n8nio/n8n
    command: worker
    environment:
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
    deploy:
      replicas: 4

  redis:
    image: redis:alpine

  postgres:
    image: postgres:14
```

**2. Load Balancer Configuration**
```nginx
upstream n8n_cluster {
    least_conn;
    server n8n-1:5678;
    server n8n-2:5678;
    keepalive 32;
}

server {
    location / {
        proxy_pass http://n8n_cluster;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}
```

**3. Database High Availability**
- Use PostgreSQL with streaming replication
- Or managed service (AWS RDS, Google Cloud SQL)
- Enable connection pooling (PgBouncer)

**4. Redis Cluster for Queue**
```yaml
redis:
  image: redis:alpine
  command: redis-server --appendonly yes
  volumes:
    - redis_data:/data
  deploy:
    replicas: 3
```

**5. Health Checks**
```yaml
healthcheck:
  test: ["CMD", "wget", "-q", "--spider", "http://localhost:5678/healthz"]
  interval: 30s
  timeout: 10s
  retries: 3
```

**6. Auto-Scaling**
```yaml
# Kubernetes HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          averageUtilization: 70
```

complexity: enterprise


instruction: How do I implement SSO/SAML authentication for n8n?

output:
**SSO/SAML Authentication for n8n**

**1. SAML Configuration**
```bash
# Environment variables for SAML
N8N_SSO_SAML_ENABLED=true
N8N_SSO_SAML_METADATA_URL=https://idp.company.com/metadata.xml
N8N_SSO_SAML_ISSUER=n8n-production
N8N_SSO_SAML_CALLBACK_URL=https://n8n.company.com/rest/sso/saml/callback
```

**2. Okta Integration**
```xml
<!-- SAML Attribute Mapping -->
<Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
  <AttributeValue>user.email</AttributeValue>
</Attribute>
<Attribute Name="firstName" ...>user.firstName</Attribute>
<Attribute Name="lastName" ...>user.lastName</Attribute>
```

**3. Azure AD Setup**
1. Register n8n as Enterprise Application
2. Configure SAML SSO with:
   - Identifier: `n8n-production`
   - Reply URL: `https://n8n.company.com/rest/sso/saml/callback`
3. Download Federation Metadata XML
4. Set `N8N_SSO_SAML_METADATA_URL` to metadata URL

**4. Role Mapping**
```javascript
// Map SAML groups to n8n roles
const samlGroups = user.attributes['memberOf'];
const roleMapping = {
  'n8n-admins': 'owner',
  'n8n-editors': 'admin',
  'n8n-viewers': 'member'
};

const n8nRole = samlGroups
  .map(g => roleMapping[g])
  .find(r => r) || 'member';
```

**5. Just-In-Time Provisioning**
- Enable auto-creation of users on first login
- Map SAML attributes to n8n user fields
- Auto-assign to default workspace

**6. Session Management**
```bash
# Session configuration
N8N_USER_MANAGEMENT_JWT_SECRET=your-secure-secret
N8N_USER_MANAGEMENT_JWT_DURATION_HOURS=8
```


instruction: How do I implement enterprise security compliance in n8n?

output:
**Enterprise Security Compliance for n8n**

**1. Encryption at Rest**
```bash
# Database encryption
POSTGRES_SSL_MODE=require
N8N_ENCRYPTION_KEY=your-32-character-encryption-key
```

**2. Encryption in Transit**
```nginx
# Force HTTPS
server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/certs/n8n.crt;
    ssl_certificate_key /etc/ssl/private/n8n.key;
    ssl_protocols TLSv1.2 TLSv1.3;
}
```

**3. Audit Logging**
```javascript
// Custom audit logging sub-workflow
// Called at start/end of sensitive workflows
const auditLog = {
  timestamp: new Date().toISOString(),
  workflowId: $workflow.id,
  workflowName: $workflow.name,
  executionId: $execution.id,
  userId: $execution.customData?.userId,
  action: 'workflow_executed',
  ipAddress: $input.first().json.headers['x-forwarded-for'],
  userAgent: $input.first().json.headers['user-agent']
};

await sendToSIEM(auditLog);
```

**4. Data Masking**
```javascript
// Mask sensitive data in logs/outputs
function maskSensitive(data) {
  const sensitiveFields = ['ssn', 'creditCard', 'password', 'apiKey'];
  const masked = { ...data };

  for (const field of sensitiveFields) {
    if (masked[field]) {
      masked[field] = '***MASKED***';
    }
  }
  return masked;
}
```

**5. Access Control**
- Enable RBAC in n8n settings
- Create role-based workflow folders
- Use credential sharing with minimal scope

**6. Compliance Checklist**
| Standard | n8n Configuration |
|----------|-------------------|
| SOC 2 | Audit logs, encryption, access control |
| HIPAA | Data encryption, audit trails, BAA with hosting |
| GDPR | Data retention policies, anonymization |
| PCI-DSS | Network segmentation, encryption, logging |