n8n on AWS Fargate with PostgreSQL RDS: Quick Start Guide
Prerequisites: AWS account, domain name, basic familiarity with AWS Console
Time to deploy: 45-60 minutes
Monthly cost: ~$20-30 (or ~$10 with Free Tier RDS)
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ Internet Traffic │
│ (HTTPS Port 443) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────────┐
│ Application Load │ ← ACM Certificate
│ Balancer (ALB) │ (Free SSL)
│ Security Group: │
│ - Allow 443 from │
│ 0.0.0.0/0 │
└────────────┬───────────┘
│ HTTP Port 5678
▼
┌────────────────────────┐
│ ECS Fargate │
│ (n8n Container) │ ← Downloads RDS cert
│ Security Group: │ on startup
│ - Allow 5678 from ALB │
│ - Allow 443 public │
└────────┬───────────────┘
│ PostgreSQL Port 5432
▼
┌────────────────────────┐
│ RDS PostgreSQL │
│ (Persistent Storage) │
│ Security Group: │
│ - Allow 5432 from ECS │
└────────────────────────┘
All resources in same VPC
Deployment Flow
Step 1: Create RDS Database (10 mins)
RDS Dashboard → Create Database
Critical settings:
Engine: PostgreSQL (latest version)
Template: Free tier (or Production)
DB identifier:
n8n-dbMaster username:
postgresMaster password:
[generate strong password]⚠️ Save thisInitial database name:
n8n⚠️ Don't skip thisPublic access: No
VPC Security Group: Create new
n8n-db-sg
Save: RDS endpoint (e.g., n8n-db.xxx.rds.amazonaws.com)
Step 2: Request SSL Certificate (5 mins)
Certificate Manager → Request Certificate
Domain:
n8n.yourdomain.comValidation: DNS validation
Click Create records in Route 53 (if using Route 53)
OR manually add CNAME to your registrar:
Type: CNAMEHost: _abc123.n8n (remove .yourdomain.com part)Value: _xyz789.acm-validations.aws
Wait: Status changes to Issued (5-30 mins)
Step 3: Create Security Groups (5 mins)
EC2 Dashboard → Security Groups → Create 3 groups
Group 1: ALB Security Group
Name: n8n-alb-sg
Inbound: HTTPS (443) from 0.0.0.0/0
Group 2: ECS Security Group
Name: n8n-ecs-sg
Inbound:
- Custom TCP (5678) from n8n-alb-sg
- HTTPS (443) from 0.0.0.0/0
Group 3: Update Database Security Group
Find: n8n-db-sg (created in Step 1)
Edit Inbound Rules:
- PostgreSQL (5432) from n8n-ecs-sg
Security flow diagram:
Internet → [443] → ALB (n8n-alb-sg)
↓
[5678 HTTP]
↓
Container (n8n-ecs-sg)
↓
[5432 PostgreSQL]
↓
RDS Database (n8n-db-sg)
Step 4: Create Task Definition (10 mins)
ECS Dashboard → Task Definitions → Create New
Infrastructure:
Launch type: AWS Fargate
Task size: 1 vCPU, 2 GB
Container:
Name:
n8nImage:
n8nio/n8n:latestPort:
5678
Critical: Docker Configuration:
Entry Point: sh,-c
Command:
mkdir -p /home/node/certs && wget https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem -O /home/node/certs/rds-ca.pem && /docker-entrypoint.sh
Environment Variables (all required):
| Key | Value | Notes |
DB_TYPE | postgresdb | |
DB_POSTGRESDB_HOST | [RDS endpoint] | From Step 1 |
DB_POSTGRESDB_PORT | 5432 | |
DB_POSTGRESDB_DATABASE | n8n | |
DB_POSTGRESDB_USER | postgres | |
DB_POSTGRESDB_PASSWORD | [your password] | From Step 1 |
DB_POSTGRESDB_SSL_CA | /home/node/certs/rds-ca.pem | |
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED | false | Fixes SSL error |
N8N_ENCRYPTION_KEY | [random 32-char string] | ⚠️ Save permanently |
WEBHOOK_URL | https://n8n.yourdomain.com/ | Your actual domain |
GENERIC_TIMEZONE | Africa/Lagos | Your timezone |
TZ | Africa/Lagos | Same as above |
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS | false | Suppress warning |
Generate encryption key:
openssl rand -base64 32
Step 5: Create Cluster & Service (15 mins)
ECS → Clusters → Create Cluster
Cluster:
Name:
n8n-clusterInfrastructure: AWS Fargate
Service (inside cluster):
Task Definition:
n8n-task(latest revision)Service name:
n8n-serviceDesired tasks:
1
Networking:
VPC: Same as RDS
Subnets: Select 2+ (different AZs)
Security Group:
n8n-ecs-sgPublic IP: Turn ON ⚠️ (needed for Docker pull)
Load Balancer:
Type: Application Load Balancer
Name:
n8n-albListener:
Port: 443
Protocol: HTTPS
Certificate: Select your ACM certificate
Target Group:
Name:
n8n-tgProtocol: HTTP (not HTTPS)
Port: 5678 ⚠️ (not 80!)
Health check path:
/healthz
Service deployment diagram:
┌─────────────────────────────────────────┐
│ 1. ECS launches container │
│ - Pulls n8nio/n8n:latest │
│ - Runs startup command │
│ - Downloads RDS certificate │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 2. Container connects to RDS │
│ - Runs database migrations │
│ - Initializes n8n │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 3. ALB health checks start │
│ - Pings /healthz every 30s │
│ - Waits for 200 OK response │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 4. Service status: Active │
│ - Container status: Running │
│ - Target status: Healthy │
└─────────────────────────────────────────┘
Get Load Balancer DNS:
EC2 → Load Balancers → n8n-alb → Copy DNS name
Example: n8n-alb-123456789.us-east-1.elb.amazonaws.com
Step 6: Configure DNS (5 mins)
Add traffic CNAME in your registrar:
Namecheap:
Type: CNAME Record
Host: n8n
Value: n8n-alb-123456789.us-east-1.elb.amazonaws.com
TTL: Automatic
GoDaddy:
Type: CNAME
Name: n8n
Value: [ALB DNS name]
TTL: 600
Cloudflare:
Type: CNAME
Name: n8n
Target: [ALB DNS name]
Proxy: DNS only (grey cloud)
Wait: 5-15 minutes for DNS propagation
Test:
nslookup n8n.yourdomain.com
Step 7: Access n8n (5 mins)
Open browser:
https://n8n.yourdomain.comCreate owner account
Start building workflows!
Success checklist:
✅ HTTPS with valid certificate (lock icon)
✅ Can create account (database working)
✅ Webhook URLs show your domain (not localhost)
Verification & Troubleshooting
Check Container Logs
ECS → Clusters → n8n-cluster → Services → n8n-service
→ Tasks → [click task] → Logs tab
Successful startup:
'/home/node/certs/rds-ca.pem' saved
Initializing n8n process
Starting migration...
Finished migration...
Editor is now accessible via:
http://localhost:5678
Common Issues Flow Chart
Problem: Container crashes immediately
│
├─→ Check logs for "Command sh not found"
│ └─→ Fix: Entry Point should be "sh,-c"
│
├─→ Check logs for "database does not exist"
│ └─→ Fix: Recreate RDS with Initial database name = n8n
│
├─→ Check logs for "Connection refused" (port 5432)
│ └─→ Fix: Edit n8n-db-sg, allow 5432 from n8n-ecs-sg
│
└─→ Check logs for "self-signed certificate"
└─→ Fix: Add DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=false
Problem: Load Balancer shows "Not reachable"
│
└─→ Edit n8n-alb-sg security group
└─→ Add rule: HTTPS (443) from 0.0.0.0/0
Problem: Target Group shows "Unhealthy"
│
├─→ Check Target Group port = 5678
│
├─→ Check health check path = /healthz
│
└─→ Check n8n-ecs-sg allows 5678 from n8n-alb-sg
Problem: Webhooks show "localhost"
│
└─→ Add WEBHOOK_URL environment variable
└─→ Create new Task Definition revision
└─→ Update Service → Force new deployment
Quick Reference
DNS Records (You Need Both)
Record 1: Certificate Validation (created in Step 2)
Host: _abc123xyz.n8n
Value: _xyz789.acm-validations.aws
Purpose: Keeps SSL certificate valid
Record 2: Traffic Routing (created in Step 6)
Host: n8n
Value: n8n-alb-123456789.us-east-1.elb.amazonaws.com
Purpose: Routes users to your n8n
Security Groups Summary
┌────────────────────────────────────────────┐
│ n8n-alb-sg (Load Balancer) │
│ Inbound: 443 ← 0.0.0.0/0 │
└────────────┬───────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ n8n-ecs-sg (Container) │
│ Inbound: 5678 ← n8n-alb-sg │
│ 443 ← 0.0.0.0/0 │
└────────────┬───────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ n8n-db-sg (Database) │
│ Inbound: 5432 ← n8n-ecs-sg │
└────────────────────────────────────────────┘
Important URLs to Save
RDS endpoint:
n8n-db.xxx.rds.amazonaws.comLoad Balancer DNS:
n8n-alb-xxx.elb.amazonaws.comYour n8n URL:
https://n8n.yourdomain.comCloudWatch logs:
/ecs/n8n-task
Credentials to Save Permanently
⚠️ RDS password: From Step 1
⚠️ N8N_ENCRYPTION_KEY: From Step 4
⚠️ n8n login: Email/password you create
Scaling Quick Guide
Vertical Scaling (More Power)
1. Task Definition → Create new revision
2. Change: 1 vCPU/2GB → 2 vCPU/4GB
3. Service → Update → Select new revision
4. Force new deployment
Cost: Doubles from $36/mo to $72/mo
Horizontal Scaling (More Containers)
1. Service → Update
2. Desired tasks: 1 → 3
3. Update
Cost: 3x current container cost
When to scale:
CPU consistently >80%
Memory consistently >90%
Workflows queuing up (delays in execution)
Webhooks timing out
Updating n8n Version
# Option 1: Latest (auto-updates)
Task Definition: n8nio/n8n:latest
# Option 2: Pinned version (more control)
Task Definition: n8nio/n8n:1.122.5
To update:
1. Create new Task Definition revision (no changes needed)
2. Update Service → Force new deployment
3. Wait for health checks to pass
Cost Breakdown
┌─────────────────────────────┬──────────────┐
│ Service │ Monthly Cost │
├─────────────────────────────┼──────────────┤
│ Fargate (1 vCPU, 2GB) │ ~$36 │
│ RDS PostgreSQL (db.t3.micro)│ ~$15 │
│ Application Load Balancer │ ~$22 │
│ Data Transfer │ ~$5 │
│ CloudWatch Logs │ ~$3 │
├─────────────────────────────┼──────────────┤
│ TOTAL │ ~$81/month │
│ (With Free Tier RDS) │ ~$66/month │
└─────────────────────────────┴──────────────┘
Optimization tips:
Use db.t4g.micro instead of db.t3.micro (-20%)
Reduce to 0.5 vCPU / 1GB if light usage (-50%)
Set CloudWatch log retention to 7 days (-60%)
Post-Deployment Checklist
[ ] Test creating a workflow
[ ] Test webhook URLs (should show your domain, not localhost)
[ ] Set up email notifications (optional)
[ ] Create CloudWatch alarm for service down
[ ] Test database backup restoration
[ ] Document your setup (save credentials, architecture notes)
[ ] Set billing alert in AWS ($100 threshold)
Next Steps
Essential (First Week):
Build your first automation workflow
Test webhooks with external service (Stripe, GitHub, etc.)
Monitor CloudWatch logs for errors
Set up at least one alarm (service down)
Recommended (First Month):
Move secrets to AWS Secrets Manager
Set up automated RDS snapshots before major changes
Review costs weekly, right-size resources
Create staging environment (duplicate setup)
Advanced (As You Scale):
Implement worker nodes for high-volume processing
Add CloudFront CDN if serving static content
Use Fargate Spot for non-critical workers (-70% cost)
Set up multi-region deployment for HA
Support Resources
n8n Docs: docs.n8n.io
n8n Community: community.n8n.io
AWS Support: Check service health dashboard
Debugging: CloudWatch logs at
/ecs/n8n-task
Complete Flow Diagram
┌───────────────────────────────────────────────────────────┐
│ DEPLOYMENT FLOW │
└───────────────────────────────────────────────────────────┘
CREATE INFRASTRUCTURE
│
├─→ [RDS PostgreSQL]
│ • Database: n8n
│ • Security: n8n-db-sg
│ • Endpoint saved
│
├─→ [ACM Certificate]
│ • Domain: n8n.yourdomain.com
│ • Validation: DNS CNAME
│ • Status: Issued ✓
│
└─→ [Security Groups]
• n8n-alb-sg (ALB)
• n8n-ecs-sg (Container)
• n8n-db-sg (Database)
CONFIGURE APPLICATION
│
├─→ [Task Definition]
│ • Image: n8nio/n8n:latest
│ • Entry Point: sh,-c
│ • Command: Download RDS cert + start
│ • Environment: 13 variables
│
└─→ [ECS Cluster + Service]
• Cluster: n8n-cluster
• Service: n8n-service
• Launch: Fargate
• Load Balancer: ALB + Target Group
CONNECT NETWORKING
│
└─→ [DNS Configuration]
• Validation CNAME (for cert)
• Traffic CNAME (for users)
• Propagation: 5-15 mins
VERIFY & USE
│
├─→ Container starts
│ • Downloads certificate
│ • Connects to RDS
│ • Runs migrations
│ • Health check passes
│
└─→ Access via browser
• https://n8n.yourdomain.com
• Create owner account
• Build workflows ✓
Deployment time: 45-60 minutes
Difficulty: Intermediate
Production-ready: Yes
Maintenance: Low (managed services)